Cột không xác định ở đâu khoản


126

Tôi có một truy vấn đơn giản:

SELECT u_name AS user_name FROM users WHERE user_name = "john";

Tôi nhận được Unknown Column 'user_name' in where clause. Tôi không thể tham khảo 'user_name'trong các phần khác của tuyên bố ngay cả sau đó select 'u_name as user_name'?

Câu trả lời:


94

SQL được đánh giá ngược, từ phải sang trái. Vì vậy, mệnh đề where được phân tích cú pháp và đánh giá trước mệnh đề select. Do đó, việc đặt bí danh của u_name thành user_name vẫn chưa xảy ra.


30
Thay vì "ngược" tôi nghĩ sẽ có ý nghĩa hơn khi nói "từ trong ra ngoài"
Joe Phillips

4
Sẽ có ý nghĩa hơn khi nói rằng toàn bộ câu lệnh được phân tích cú pháp, biến đổi và tối ưu hóa toàn bộ trong một quy trình nhiều tầng phức tạp. "SQL được đánh giá ngược, từ phải sang trái" là sai
David Aldridge

3
Câu trả lời không đầy đủ khi người dùng hỏi liệu 'user_name' có thể được sử dụng trong câu lệnh hay không, ví dụ như 'HAVING'
luke_mclachlan

45

Thế còn:

SELECT u_name AS user_name FROM users HAVING user_name = "john";

16
Tại sao bạn sẽ sử dụng HAVINGthay vì WHEREtrong trường hợp này?
PeteGO

4
@PeteGO tham khảo câu trả lời của Paul Dixon. tldr; HAVING được đánh giá muộn hơn WHERE và quan trọng hơn là CHỌN.
jairbow

38

Xem trang hướng dẫn sử dụng MySQL sau: http://dev.mysql.com/doc/refman/5.0/en/select.html

"Một select_expr có thể được cung cấp một bí danh bằng cách sử dụng AS alias_name. Bí danh được sử dụng làm tên cột của biểu thức và có thể được sử dụng trong các mệnh đề GROUP BY, ORDER BY hoặc HAVING."

(...)

Không được phép tham chiếu bí danh cột trong mệnh đề WHERE, vì giá trị cột có thể chưa được xác định khi mệnh đề WHERE được thực thi. Xem Phần B.5.4.4, Các vấn đề về mối quan hệ với Bí danh Cột.


Ngoài ra, lưu ý (từ người đàn ông MySQL): Tiêu chuẩn SQL yêu cầu HAVING phải chỉ tham chiếu các cột trong mệnh đề GROUP BY hoặc các cột được sử dụng trong các hàm tổng hợp. Tuy nhiên, MySQL hỗ trợ một phần mở rộng cho hành vi này và cho phép HAVING tham khảo các cột trong danh sách CHỌN và các cột trong các truy vấn con bên ngoài.
Vincent Pazeller

12
select u_name as user_name from users where u_name = "john";

Hãy nghĩ về nó như thế này, mệnh đề where của bạn đánh giá đầu tiên, để xác định hàng nào (hoặc hàng đã nối) cần được trả về. Khi mệnh đề where được thực thi, mệnh đề select sẽ chạy cho nó.

Để nói một cách tốt hơn, hãy tưởng tượng điều này:

select distinct(u_name) as user_name from users where u_name = "john";

Bạn không thể tham khảo nửa đầu mà không có thứ hai. Trường hợp luôn được đánh giá đầu tiên, sau đó là mệnh đề chọn.


11

Nếu bạn đang cố thực hiện một truy vấn như sau (tìm tất cả các nút có ít nhất một tệp đính kèm) trong đó bạn đã sử dụng câu lệnh CHỌN để tạo trường mới không thực sự tồn tại trong cơ sở dữ liệu và thử sử dụng bí danh cho kết quả đó bạn sẽ gặp phải cùng một vấn đề:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes
WHERE attachmentcount > 0;

Bạn sẽ gặp lỗi "Cột không xác định 'tệp đính kèm' trong mệnh đề WHERE".

Giải pháp thực sự khá đơn giản - chỉ cần thay thế bí danh bằng câu lệnh tạo ra bí danh, ví dụ:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes 
WHERE (SELECT (COUNT(*) FROM attachments WHERE attachments.nodeid = nodes.id) > 0;

Bạn vẫn sẽ nhận được bí danh được trả về, nhưng bây giờ SQL không nên sử dụng bí danh.


1
Tôi đã phải đối mặt với vấn đề chính xác này, và đã bắt gặp câu trả lời của bạn - cảm ơn bạn! Chỉ cần lưu ý, nó (có thể hiểu được) hơi chậm trên các cơ sở dữ liệu lớn, nhưng dù sao tôi cũng đang xử lý một thiết lập cơ sở dữ liệu kế thừa ngu ngốc.
Liam Newmarch

Tôi tin rằng bạn có thêm một (truy vấn của bạn trước khi (COUNT(*)không được đóng ở bất cứ đâu.
tftd

3
Nhưng không phải câu lệnh CHỌN chạy hai lần?
Matej

Tôi cho đến nay không có chuyên gia mysql nhưng điều này có vẻ rất kém. Tôi đã có kinh nghiệm rằng các lựa chọn lồng nhau làm cho một truy vấn chậm hơn nhiều.
GDY

8

Định nghĩa của bạn aliaskhông được hoan nghênh bởi WHEREmệnh đề bạn phải sử dụng HAVINGmệnh đề cho điều này

SELECT u_name AS user_name FROM users HAVING user_name = "john";

HOẶC bạn có thể trực tiếp sử dụng tên cột ban đầu với WHERE

SELECT u_name AS user_name FROM users WHERE u_name = "john";

Giống như bạn có kết quả là bí danh do người dùng định nghĩa là kết quả của truy vấn con hoặc bất kỳ phép tính nào, nó sẽ được truy cập bởi HAVINGmệnh đề không phải bởiWHERE

SELECT u_name AS user_name ,
(SELECT last_name FROM users2 WHERE id=users.id) as user_last_name
FROM users  WHERE u_name = "john" HAVING user_last_name ='smith'

7

Hoặc:

SELECT u_name AS user_name
FROM   users
WHERE  u_name = "john";

hoặc là:

SELECT user_name
from
(
SELECT u_name AS user_name
FROM   users
)
WHERE  u_name = "john";

Cái sau phải giống như cái trước nếu RDBMS hỗ trợ biến vị ngữ đẩy vào khung nhìn nội tuyến.



5

Không, bạn cần phải chọn nó với tên chính xác. Nếu bạn đã cho bảng bạn chọn từ một bí danh, bạn có thể sử dụng bảng đó.


2

Không, bạn không thể. user_name không tồn tại cho đến thời gian trả về.


1

Cột không xác định trong WHEREmệnh đề gây ra bởi dòng 1 và 2 và được giải quyết bằng dòng 3:

  1. $sql = "SELECT * FROM users WHERE username =".$userName;
  2. $sql = "SELECT * FROM users WHERE username =".$userName."";
  3. $sql = "SELECT * FROM users WHERE username ='".$userName."'";

Bạn đã thay đổi điều gì và tại sao? Ngoài ra, tại sao bạn lại đăng mã được mở rộng rãi để tiêm SQL?
Nico Haase

1

Có thể là nó giúp.

Bạn có thể

SET @somevar := '';
SELECT @somevar AS user_name FROM users WHERE (@somevar := `u_name`) = "john";

Nó hoạt động.

NHƯNG KIẾM ĐƯỢC NHỮNG GÌ BẠN LÀM GÌ!

  • Các chỉ mục KHÔNG được sử dụng ở đây
  • Sẽ được quét FULL BẢNG - bạn chưa chỉ định phần GIỚI HẠN 1
  • Vì vậy, - NHỮNG CÂU HỎI NÀY SILL ĐƯỢC SLLLOOOOOOW trên những chiếc bàn lớn.

Nhưng, có thể nó giúp trong một số trường hợp


0

Trong khi bạn có thể đặt bí danh cho các bảng trong truy vấn của mình (ví dụ: "CHỌN u.username TỪ người dùng u;"), bạn phải sử dụng tên thật của các cột bạn đang tham chiếu. NHƯ chỉ tác động làm thế nào các lĩnh vực được trả lại.


Tôi nghĩ rằng bạn có thể sử dụng bí danh trong một số RDBMS như MySql chẳng hạn. Bạn đã đúng cho Sql Server.
PeteGO

0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"

Tại sao bạn muốn sử dụng truy vấn phụ? Đơn giản hơn nhiều mà không có.
PeteGO

0

Chỉ có vấn đề này.

Hãy chắc chắn rằng không có khoảng trắng trong tên của thực thể trong cơ sở dữ liệu.

ví dụ: 'user_name' thay vì 'user_name'


-1

thử tác vụ của bạn bằng điều kiện IN hoặc điều kiện OR và truy vấn này cũng hoạt động trên spark-1.6.x

 SELECT  patient, patient_id FROM `patient` WHERE patient IN ('User4', 'User3');

hoặc là

SELECT  patient, patient_id FROM `patient` WHERE patient = 'User1' OR patient = 'User2';

-1

Đối với tôi, gốc rễ của vấn đề là một số mà tôi đã sao chép để sử dụng trong mệnh đề WHERE. Con số có biểu tượng "vô hình", ít nhất là đối với MySQL Workbench. Tôi đã đặt số trong bảng điều khiển Chrome có thể nhìn thấy rõ.


-2

Tôi đã có cùng một vấn đề, tôi thấy điều này hữu ích.

mysql_query("SELECT * FROM `users` WHERE `user_name`='$user'");

nhớ đặt $ user trong dấu ngoặc đơn ''.


1
Mã đó được mở rộng để tiêm SQL. Không ai nên sử dụng mã này để giải quyết vấn đề đã cho
Nico Haase
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.