คอลัมน์ที่ไม่รู้จักในที่ซึ่งข้อ


126

ฉันมีคำถามง่ายๆ:

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

ฉันเข้าใจUnknown Column 'user_name' in where clauseแล้ว ฉันไม่สามารถอ้างถึง'user_name'ในส่วนอื่น ๆ ของแถลงการณ์ได้select 'u_name as user_name'หรือไม่?

คำตอบ:


94

SQL จะประเมินย้อนหลังจากขวาไปซ้าย ดังนั้นตำแหน่งที่จะแยกวิเคราะห์และประเมินก่อนที่จะเลือกอนุประโยค ด้วยเหตุนี้การตั้งนามแฝงของ u_name เป็น user_name จึงยังไม่เกิดขึ้น


30
แทนที่จะ "ถอยหลัง" ฉันคิดว่ามันสมเหตุสมผลกว่าที่จะพูดว่า "จากภายใน"
โจฟิลลิปส์

4
มันสมเหตุสมผลกว่าที่จะบอกว่าข้อความทั้งหมดถูกแยกวิเคราะห์เปลี่ยนรูปและปรับให้เหมาะสมโดยรวมในกระบวนการหลายขั้นตอนที่ซับซ้อน "SQL ถูกประเมินย้อนกลับจากขวาไปซ้าย" ผิด
David Aldridge

3
คำตอบที่ไม่สมบูรณ์ตามที่ผู้ใช้ถามว่า 'user_name' สามารถใช้ในคำสั่งได้หรือไม่ซึ่งสามารถอยู่หลังเช่น 'HAVING'
luke_mclachlan

45

สิ่งที่เกี่ยวกับ:

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

16
ทำไมคุณถึงใช้HAVINGแทนWHEREในกรณีนี้?
PeteGO

4
@PeteGO อ้างถึงคำตอบของ Paul Dixon TLDR; HAVING ได้รับการประเมินช้ากว่า WHERE และที่สำคัญกว่านั้นคือ SELECT
jairbow

38

ดูหน้าคู่มือ MySQL ต่อไปนี้: http://dev.mysql.com/doc/refman/5.0/en/select.html

"select_expr สามารถกำหนดนามแฝงได้โดยใช้ AS alias_name นามแฝงใช้เป็นชื่อคอลัมน์ของนิพจน์และสามารถใช้ใน GROUP BY, ORDER BY หรือ HAVING clauses"

( ... )

ไม่อนุญาตให้อ้างถึงนามแฝงคอลัมน์ในส่วนคำสั่ง WHERE เนื่องจากค่าคอลัมน์อาจยังไม่ถูกกำหนดเมื่อเรียกใช้คำสั่ง WHERE ดูหัวข้อ B.5.4.4“ ปัญหาเกี่ยวกับชื่อแทนคอลัมน์”


นอกจากนี้โปรดทราบ (จาก MySQL man): มาตรฐาน SQL กำหนดให้ HAVING ต้องอ้างอิงเฉพาะคอลัมน์ใน GROUP BY clause หรือคอลัมน์ที่ใช้ในฟังก์ชันการรวม อย่างไรก็ตาม MySQL สนับสนุนส่วนขยายของพฤติกรรมนี้และอนุญาตให้ HAVING อ้างถึงคอลัมน์ในรายการ SELECT และคอลัมน์ในแบบสอบถามย่อยภายนอกด้วย
Vincent Pazeller

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

ลองนึกดูแบบนี้โดยที่ clause ของคุณจะประเมินก่อนเพื่อกำหนดว่าต้องส่งคืนแถวใด (หรือแถวที่เข้าร่วม) เมื่อเรียกใช้คำสั่ง where แล้วคำสั่ง select จะทำงาน

เพื่อให้ดีขึ้นลองนึกภาพสิ่งนี้:

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

คุณไม่สามารถอ้างอิงครึ่งแรกโดยไม่มีวินาที โดยจะได้รับการประเมินก่อนเสมอจากนั้นจึงเลือกอนุประโยค


11

หากคุณกำลังพยายามดำเนินการค้นหาดังต่อไปนี้ (ค้นหาโหนดทั้งหมดที่มีสิ่งที่แนบมาอย่างน้อยหนึ่งรายการ) ที่คุณใช้คำสั่ง SELECT เพื่อสร้างฟิลด์ใหม่ที่ไม่มีอยู่จริงในฐานข้อมูลและลองใช้ นามแฝงสำหรับผลลัพธ์นั้นคุณจะพบปัญหาเดียวกัน:

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

คุณจะได้รับข้อผิดพลาด "Unknown column" attachmentcount "ใน WHERE clause"

วิธีแก้ปัญหานั้นค่อนข้างง่าย - เพียงแค่แทนที่นามแฝงด้วยข้อความที่สร้างนามแฝงเช่น:

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;

คุณจะยังคงได้รับนามแฝงกลับมา แต่ตอนนี้ SQL ไม่ควรไปยุ่งกับนามแฝงที่ไม่รู้จัก


1
ฉันประสบปัญหานี้และพบคำตอบของคุณ - ขอบคุณ! โปรดทราบว่าฐานข้อมูลขนาดใหญ่ทำงานช้าเล็กน้อย แต่ฉันกำลังจัดการกับการตั้งค่าฐานข้อมูลที่สืบทอดมาแบบโง่ ๆ อยู่ดี
Liam Newmarch

ฉันเชื่อว่าคุณมีส่วนเสริม(ในการค้นหาของคุณก่อน(COUNT(*)ที่จะไม่ปิดทุกที่
tftd

3
แต่คำสั่ง SELECT ไม่ทำงานสองครั้ง?
Matej

ฉันไม่ใช่ผู้เชี่ยวชาญ mysql แต่ดูเหมือนว่าจะไม่มีประสิทธิภาพมากนัก ฉันพบว่าการเลือกที่ซ้อนกันทำให้แบบสอบถามช้าลงมาก
GDY

8

คำจำกัดความของคุณaliasไม่ได้รับการต้อนรับจากWHEREประโยคที่คุณต้องใช้HAVINGอนุประโยคนี้

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

หรือคุณสามารถใช้ชื่อคอลัมน์เดิมโดยตรงกับไฟล์ WHERE

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

เช่นเดียวกับที่คุณมีผลลัพธ์ในนามแฝงที่ผู้ใช้กำหนดซึ่งเป็นผลมาจากการสืบค้นย่อยหรือการคำนวณใด ๆ ที่จะเข้าถึงโดยHAVINGอนุประโยคที่ไม่ได้ใช้WHERE

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

ทั้ง:

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

หรือ:

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

หลังควรจะเหมือนกับในอดีตหาก RDBMS สนับสนุนเพรดิเคตที่ผลักเข้าไปในมุมมองในบรรทัด



5

ไม่จำเป็นต้องเลือกด้วยชื่อที่ถูกต้อง หากคุณให้ตารางที่คุณเลือกจากนามแฝงคุณสามารถใช้สิ่งนั้นได้



1

คอลัมน์ที่ไม่รู้จักในWHEREประโยคที่เกิดจากบรรทัดที่ 1 และ 2 และแก้ไขโดยบรรทัดที่ 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."'";

คุณเปลี่ยนแปลงอะไรและทำไม? นอกจากนี้เหตุใดคุณจึงโพสต์โค้ดที่เปิดกว้างสำหรับการแทรก SQL
Nico Haase

1

อาจจะช่วยได้

คุณสามารถ

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

มันได้ผล.

แต่ให้แน่ใจว่าคุณทำอะไร!

  • ดัชนีไม่ได้ใช้ที่นี่
  • จะมีการสแกนเต็มตาราง - คุณไม่ได้ระบุส่วน LIMIT 1
  • ดังนั้น - คำค้นหานี้จะปรากฏบนโต๊ะขนาดใหญ่

แต่อาจช่วยได้บ้างในบางกรณี


0

ในขณะที่คุณสามารถตั้งชื่อแทนตารางของคุณในข้อความค้นหาของคุณ (เช่น "SELECT u.username FROM users u;") คุณต้องใช้ชื่อจริงของคอลัมน์ที่คุณอ้างถึง AS จะส่งผลต่อวิธีการส่งคืนฟิลด์เท่านั้น


ฉันคิดว่าคุณสามารถใช้นามแฝงใน RDBMS บางตัวเช่น MySql เป็นต้น คุณถูกต้องสำหรับ Sql Server แม้ว่า
PeteGO

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

ทำไมคุณถึงต้องการใช้แบบสอบถามย่อย ง่ายกว่ามากหากไม่มี
PeteGO

0

เพิ่งมีปัญหานี้.

ตรวจสอบให้แน่ใจว่าไม่มีช่องว่างในชื่อของเอนทิตีในฐานข้อมูล

เช่น 'user_name' แทน 'user_name'


-1

ลองงานของคุณโดยใช้ในเงื่อนไขหรือหรือเงื่อนไขและแบบสอบถามนี้คือการทำงานในจุดประกาย 1.6.x

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

หรือ

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

-1

สำหรับฉันต้นตอของปัญหาคือตัวเลขที่ฉันคัดลอกไปใช้ในคำสั่ง WHERE ตัวเลขมีสัญลักษณ์ "มองไม่เห็น" อย่างน้อยสำหรับ MySQL Workbench ฉันวางหมายเลขไว้ในคอนโซล Chrome ซึ่งมองเห็นได้ชัดเจน


-2

ฉันมีปัญหาเดียวกันฉันพบว่าสิ่งนี้มีประโยชน์

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

อย่าลืมใส่ $ user ในเครื่องหมายคำพูดเดี่ยว


1
รหัสนั้นเปิดกว้างสำหรับการแทรก SQL ไม่มีใครควรใช้รหัสนี้เพื่อแก้ปัญหาที่กำหนด
Nico Haase
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.