ไม่สามารถใช้ชื่อตาราง PostgreSQL เพียงอย่างเดียว (“ ไม่มีความเกี่ยวข้อง”)


183

ฉันพยายามเรียกใช้สคริปต์ PHP ต่อไปนี้เพื่อทำแบบสอบถามฐานข้อมูลอย่างง่าย:

$db_host = "localhost";
$db_name = "showfinder";
$username = "user";
$password = "password";
$dbconn = pg_connect("host=$db_host dbname=$db_name user=$username password=$password")
    or die('Could not connect: ' . pg_last_error());

$query = 'SELECT * FROM sf_bands LIMIT 10';
$result = pg_query($query) or die('Query failed: ' . pg_last_error());

สิ่งนี้ทำให้เกิดข้อผิดพลาดดังต่อไปนี้:

การค้นหาล้มเหลว: ERROR: ความสัมพันธ์ "sf_bands" ไม่มีอยู่

ในตัวอย่างทั้งหมดที่ฉันสามารถหาที่ใครบางคนได้รับข้อผิดพลาดที่ระบุความสัมพันธ์ที่ไม่มีอยู่ก็เพราะพวกเขาใช้ตัวอักษรตัวพิมพ์ใหญ่ในชื่อตารางของพวกเขา ชื่อตารางของฉันไม่มีตัวอักษรตัวพิมพ์ใหญ่ มีวิธีสืบค้นตารางของฉันโดยไม่รวมชื่อฐานข้อมูลshowfinder.sf_bandsหรือไม่


2
คุณแน่ใจหรือว่าตาราง sf_bands มีอยู่ showfinder.sf_bands ทำงานหรือไม่
brian-Brazil

1
showfinder.sf_bands ทำงานได้อย่างสมบูรณ์
Keyslinger

บางทีฉันควรทราบว่าฐานข้อมูลของฉันได้รับการอพยพมาจาก MySQL
Keyslinger

คุณลอง pg_query ($ dbconn, $ query) ได้ไหม? การเชื่อมต่อโดยนัยอาจทำให้เกิดปัญหาที่ยากต่อการตรวจแก้จุดบกพร่องและอาจกำจัดเป็นปัญหาที่เป็นไปได้ คุณสามารถลองใช้ pg_dbname ($ dbconn) เพื่อให้แน่ใจว่าเชื่อมต่อกับ showfinder ได้หรือไม่?
brian-Brazil

1
+1 สำหรับการกล่าวถึงว่าตัวอักษรตัวใหญ่เป็นปัญหา ฉันใช้เวลาหนึ่งชั่วโมงเพื่อหาสาเหตุที่ฉันไม่สามารถเลือกจากตารางเดียวใน PostgreSQL เป็นโปรแกรมที่แย่มาก
Brain2000

คำตอบ:


298

จากสิ่งที่ฉันอ่านข้อผิดพลาดนี้หมายความว่าคุณไม่ได้อ้างอิงชื่อตารางอย่างถูกต้อง สาเหตุหนึ่งที่พบบ่อยคือตารางถูกกำหนดด้วยการสะกดคำตัวพิมพ์เล็กและคุณพยายามค้นหาด้วยตัวพิมพ์เล็กทั้งหมด

ในคำอื่น ๆ ต่อไปนี้ล้มเหลว:

CREATE TABLE "SF_Bands" ( ... );

SELECT * FROM sf_bands;  -- ERROR!

ใช้เครื่องหมายคำพูดคู่เพื่อกำหนดขอบเขตตัวระบุเพื่อให้คุณสามารถใช้การสะกดคำแบบตัวพิมพ์เล็กและตัวใหญ่ตามที่กำหนดในตาราง

SELECT * FROM "SF_Bands";

ความคิดเห็นของคุณอีกครั้งคุณสามารถเพิ่มสคีมาลงใน "search_path" เพื่อที่ว่าเมื่อคุณอ้างอิงชื่อตารางโดยไม่ต้องพิจารณาสคีมาของมันแบบสอบถามจะจับคู่ชื่อตารางนั้นโดยตรวจสอบแต่ละสคีมาตามลำดับ เช่นเดียวกับPATHในเชลล์หรือinclude_pathใน PHP ฯลฯ คุณสามารถตรวจสอบเส้นทางการค้นหาสคีมาปัจจุบันของคุณ:

SHOW search_path
  "$user",public

คุณสามารถเปลี่ยนเส้นทางการค้นหาสคีมาของคุณ:

SET search_path TO showfinder,public;

ดูเพิ่มเติมที่http://www.postgresql.org/docs/8.3/static/ddl-schemas.html


โอ๊ะยกโทษให้ฉัน ฉันหมายถึงว่าชื่อตารางของฉันไม่มีตัวอักษรตัวพิมพ์ใหญ่ไม่ใช่ชื่อฐานข้อมูลของฉัน
Keyslinger

13
ดูเหมือนว่าแม้ว่าคุณจะพิมพ์SELECT * FROM SF_Bandsสิ่งนี้จะยังคงล้มเหลวเนื่องจาก Postgres ตัดสินใจที่จะพิมพ์เล็กชื่อตารางให้คุณ แปลก ...
โรมัน Starkov

3
@romkyns: ใช่แล้วนี่เป็นเรื่องธรรมดาที่พบได้ทั่วไปในแบรนด์ RDBMS ซึ่งตัวระบุที่ไม่ได้คั่นถูกโฆษณาว่าเป็น "ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่" แต่มันไม่ได้เป็นแบบตัวเล็กที่แท้จริงเพราะวิธีที่พวกเขาใช้งานนั่นคือบังคับให้ตัวพิมพ์เล็ก สิ่งนี้ตรงกับชื่อของตารางเฉพาะในกรณีที่คุณอนุญาตให้ชื่อตารางลดระดับลงเมื่อคุณกำหนดตาราง ถ้าคุณใช้ตัวคั่นเครื่องหมายคำพูดคู่เมื่อคุณสร้างตารางคุณต้องใช้ตัวคั่นเมื่อคุณอ้างอิงในแบบสอบถาม
Bill Karwin

Postgres ลดขนาดชื่อตารางโดยอัตโนมัติหรือไม่หากไม่มีเครื่องหมายอัญประกาศ ช่างเป็นเรื่องที่น่ารัก ...
Andy

@Andy เมื่อคุณเขียนฐานข้อมูล SQL ของคุณเองอย่าลังเลที่จะใช้ตัวระบุแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ :)
Bill Karwin

76

ฉันมีปัญหากับเรื่องนี้และนี่คือเรื่องราว (เศร้า แต่จริง):

  1. หากชื่อตารางของคุณเป็นตัวพิมพ์เล็กทั้งหมดเช่น: บัญชีที่คุณสามารถใช้: select * from AcCounTsและมันจะทำงานได้ดี

  2. หากชื่อตารางของคุณเป็นตัวพิมพ์เล็กทั้งหมดเช่น: accounts สิ่งต่อไปนี้จะล้มเหลว: select * from "AcCounTs"

  3. หากชื่อตารางของคุณเป็นแบบตัวพิมพ์ผสมเช่น: Accounts สิ่งต่อไปนี้จะล้มเหลว: select * from accounts

  4. หากชื่อตารางของคุณเป็นแบบตัวพิมพ์ผสมเช่น: Accounts สิ่งต่อไปนี้จะใช้งานได้: select * from "Accounts"

ฉันไม่ชอบการจดจำสิ่งที่ไร้ประโยชน์เช่นนี้ แต่คุณต้อง;)


1
เหมือนกันสำหรับชื่อคอลัมน์ใน where-claus
Roland

8
5. กรณีผสมเช่นAccountsจะล้มเหลวด้วยselect * from Accounts;ฉันพบส่วนที่แปลกประหลาด: กรณีเดียวกันไม่เหมือนกัน
Roland

7
ทั้งหมดที่มีอยู่: ชื่อทั้งหมดในแบบสอบถาม postgres เป็นตัวพิมพ์เล็กเว้นแต่คุณจะใช้เครื่องหมายคำพูด
Erndob

1
ตัวเลือกที่สี่ใช้งานได้สำหรับฉัน แต่ฉันไม่ได้ใช้ PHP
Sayari

2
ขอบคุณสำหรับการวางปฏิสัมพันธ์ทั้งหมด! :)
GetHacked

16

Postgres กระบวนการสืบค้นที่แตกต่างจาก RDMS อื่น ๆ ใส่ชื่อสกีมาในเครื่องหมายคำพูดคู่หน้าชื่อตารางของคุณเช่นนี้ "SCHEMA_NAME" "SF_Bands"


7
คำตอบของคุณเพิ่มไปยังคำตอบที่ยอมรับก่อนหน้านี้แล้วเพิ่มขึ้น 22 เท่าและมีรายละเอียดมากมาย?
Yaroslav

16

วางพารามิเตอร์ dbname ในสตริงการเชื่อมต่อของคุณ มันทำงานได้สำหรับฉันในขณะที่ทุกอย่างอื่นล้มเหลว

your_schemaนอกจากนี้เมื่อทำเลือกระบุ your_tableแบบนี้:

select * from my_schema.your_table

1
ใส่ชื่อสกีมาในเช่น my_schema.my_relation ลงในแบบสอบถามช่วย
JoeTidee

2
ขอบคุณมาก! reall ช่วยฉันแก้ปัญหา! แต่มีวิธีที่ฉันสามารถละเว้นชื่อโครงการหรือไม่
Charlotte

8

ฉันมีปัญหาที่คล้ายกันใน OSX แต่พยายามที่จะเล่นด้วยคำพูดสองครั้งและคำพูดเดียว สำหรับกรณีของคุณคุณสามารถลองสิ่งนี้

$query = 'SELECT * FROM "sf_bands"'; // NOTE: double quotes on "sf_Bands"

4

นี่เป็นประโยชน์จริง ๆ

SET search_path TO schema,public;

ฉันขุดปัญหานี้มากขึ้นและค้นพบเกี่ยวกับวิธีการตั้งค่า "search_path" นี้โดยกำหนดผู้ใช้ใหม่ในฐานข้อมูลปัจจุบัน

เปิดคุณสมบัติ DataBase จากนั้นเปิดแผ่น "ตัวแปร" และเพียงเพิ่มตัวแปรนี้สำหรับผู้ใช้ของคุณด้วยค่าจริง

ดังนั้นตอนนี้ผู้ใช้ของคุณจะได้รับ schema_name นี้โดย defoultate และคุณสามารถใช้ tableName โดยไม่ต้อง schemaName


4

คุณต้องเขียนชื่อสกีมาและชื่อตารางในเครื่องหมาย qutotation ดังต่อไปนี้:

select * from "schemaName"."tableName";

1

สำหรับฉันปัญหาคือว่าฉันได้ใช้แบบสอบถามไปยังตารางนั้นขณะที่ Django เริ่มต้นได้ แน่นอนว่ามันจะผิดพลาดเพราะตารางเหล่านั้นไม่มีอยู่จริง ในกรณีของฉันมันเป็นget_or_createวิธีการภายในไฟล์ admin.py ซึ่งจะถูกดำเนินการเมื่อใดก็ตามที่ซอฟต์แวร์รันการดำเนินการใด ๆ (ในกรณีนี้คือการย้ายข้อมูล) หวังว่าจะช่วยใครซักคน


0

คุณต้องเพิ่มสคีมาก่อนเช่น

SELECT * FROM place.user_place;

หากคุณไม่ต้องการที่จะเพิ่มในแบบสอบถามทั้งหมดลองนี้:

SET search_path TO place;

ตอนนี้มันจะทำงาน:

SELECT * FROM user_place;

0

วิธีแก้ปัญหาที่ง่ายที่สุดคือเพียงเปลี่ยนชื่อตารางและชื่อคอลัมน์ทั้งหมดเป็นตัวพิมพ์เล็กและปัญหาของคุณจะได้รับการแก้ไข

ตัวอย่างเช่น:

  • เปลี่ยนTable_Nameเป็นtable_name และ
  • เปลี่ยนColumnNameเป็นcolumnname
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.