Không thể đơn giản sử dụng tên bảng PostgreSQL (mối quan hệ trên mạng không tồn tại)


183

Tôi đang cố chạy đoạn mã PHP sau để thực hiện một truy vấn cơ sở dữ liệu đơn giản:

$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());

Điều này tạo ra lỗi sau:

Truy vấn không thành công: ERROR: mối quan hệ "sf_band" không tồn tại

Trong tất cả các ví dụ tôi có thể tìm thấy nơi ai đó gặp lỗi cho biết mối quan hệ không tồn tại, đó là vì họ sử dụng chữ in hoa trong tên bảng của họ. Tên bảng của tôi không có chữ hoa. Có cách nào để truy vấn bảng của tôi mà không bao gồm tên cơ sở dữ liệu, nghĩa là showfinder.sf_bands?


2
Bạn có chắc chắn rằng bảng sf_band tồn tại? Showfinder.sf_band có hoạt động không?
brian-brazil

1
showfinder.sf_band hoạt động hoàn hảo
Keyslinger

Có lẽ tôi nên lưu ý rằng cơ sở dữ liệu của tôi đã được di chuyển từ MySQL
Keyslinger

Bạn có thể thử pg_query ($ dbconn, $ query) không? Kết nối ngầm có thể gây ra các vấn đề khó gỡ lỗi, cũng có thể loại bỏ nó như một vấn đề có thể xảy ra. Bạn cũng có thể thử pg_dbname ($ dbconn) để đảm bảo rằng nó thực sự được kết nối với showfinder không?
brian-brazil

1
+1 để đề cập rằng các chữ cái viết hoa là vấn đề. Tôi đã dành một giờ để cố gắng tìm ra lý do tại sao tôi không thể chọn từ một bảng duy nhất trong PostgreSQL. Thật là một chương trình khủng khiếp.
Brain2000

Câu trả lời:


298

Từ những gì tôi đã đọc, lỗi này có nghĩa là bạn không tham chiếu chính xác tên bảng. Một lý do phổ biến là bảng được xác định bằng chính tả chữ thường và bạn đang cố gắng truy vấn nó với tất cả chữ thường.

Nói cách khác, những điều sau đây không thành công:

CREATE TABLE "SF_Bands" ( ... );

SELECT * FROM sf_bands;  -- ERROR!

Sử dụng dấu ngoặc kép để phân định định danh để bạn có thể sử dụng chính tả trường hợp hỗn hợp cụ thể khi bảng được xác định.

SELECT * FROM "SF_Bands";

Nhận xét của bạn, bạn có thể thêm một lược đồ vào "search_path" để khi bạn tham chiếu một tên bảng mà không đủ điều kiện cho lược đồ của nó, truy vấn sẽ khớp với tên bảng đó bằng cách kiểm tra từng lược đồ theo thứ tự. Giống như PATHtrong trình bao hoặc include_pathtrong PHP, v.v. Bạn có thể kiểm tra đường dẫn tìm kiếm lược đồ hiện tại của mình:

SHOW search_path
  "$user",public

Bạn có thể thay đổi đường dẫn tìm kiếm lược đồ của mình:

SET search_path TO showfinder,public;

Xem thêm http://www.postgresql.org/docs/8.3/static/ddl-schemas.html


Rất tiếc, hãy tha thứ cho tôi. Tôi muốn nói rằng tên bảng của tôi không có chữ hoa, không phải tên cơ sở dữ liệu của tôi.
Keyslinger

13
Có vẻ như ngay cả khi bạn nhập SELECT * FROM SF_Bandscái này vẫn sẽ thất bại, vì Postgres quyết định viết thường tên bảng đó cho bạn.
Thật

3
@romkyns: Vâng, điều này thực sự khá phổ biến trên các thương hiệu RDBMS, rằng các số nhận dạng không giới hạn được quảng cáo là "không phân biệt chữ hoa chữ thường". Nhưng họ không thực sự vô cảm vì cách họ đã thực hiện đó là ép chữ thường. Điều này chỉ khớp với tên của bảng nếu bạn đã cho phép tên bảng được hạ xuống khi bạn xác định bảng. Nếu bạn sử dụng dấu phân cách kép khi bạn TẠO BẢNG, bạn phải sử dụng dấu phân cách khi bạn tham chiếu nó trong các truy vấn.
Bill Karwin

Postgres tự động viết thường tên bảng nếu chúng không có dấu ngoặc kép? Thật tuyệt vời ...
Andy

@Andy, khi bạn viết cơ sở dữ liệu SQL của riêng mình, vui lòng thực hiện các định danh không phân biệt chữ hoa chữ thường theo một cách khác. :)
Bill Karwin

76

Tôi đã có vấn đề với điều này và đây là câu chuyện (buồn nhưng có thật):

  1. Nếu tên bảng của bạn là tất cả chữ thường như: tài khoản bạn có thể sử dụng: select * from AcCounTsvà nó sẽ hoạt động tốt

  2. Nếu tên bảng của bạn là tất cả chữ thường như: accounts Điều sau đây sẽ thất bại: select * from "AcCounTs"

  3. Nếu tên bảng của bạn là trường hợp hỗn hợp như: Accounts Điều sau đây sẽ thất bại: select * from accounts

  4. Nếu tên bảng của bạn là trường hợp hỗn hợp như: Accounts Sau đây sẽ hoạt động OK: select * from "Accounts"

Tôi không thích nhớ những thứ vô dụng như thế này nhưng bạn phải làm vậy;)


1
Tương tự cho tên cột trong mệnh đề
Roland

8
5. Trường hợp hỗn hợp, như Accounts, sẽ thất bại với select * from Accounts;tôi thấy phần kỳ lạ nhất: trường hợp tương tự KHÔNG giống nhau.
Roland

7
Tất cả chỉ có thế: tất cả các tên trong truy vấn postgres đều là chữ thường, trừ khi bạn sử dụng dấu ngoặc kép.
Erndob

1
Tùy chọn thứ tư làm việc cho tôi, mặc dù tôi không sử dụng PHP
Sayari

2
Cảm ơn đã đặt ra tất cả các tương tác! :)
GetHacked

16

Postgres truy vấn quá trình khác với RDMS khác. Đặt tên lược đồ trong trích dẫn kép trước tên bảng của bạn như thế này, "SCHema_NAME". "SF_Bands"


7
Câu trả lời của bạn thêm gì vào câu trả lời được chấp nhận trước đó, được nâng cấp 22 lần và với rất nhiều chi tiết?
Yaroslav

16

Đặt tham số dbname trong chuỗi kết nối của bạn. Nó làm việc cho tôi trong khi mọi thứ khác đều thất bại.

Ngoài ra khi thực hiện chọn, chỉ định your_schema. your_tablenhư thế này:

select * from my_schema.your_table

1
Đặt tên lược đồ vào, ví dụ my_schema.my_relation vào truy vấn đã giúp.
JoeTidee

2
Cảm ơn rât nhiều! Nó Reall giúp tôi giải quyết vấn đề! Nhưng có một cách mà tôi có thể bỏ qua tên chương trình?
Charlotte

8

Tôi đã có một vấn đề tương tự trên OSX nhưng đã cố gắng chơi xung quanh với dấu ngoặc kép và dấu ngoặc đơn. Đối với trường hợp của bạn, bạn có thể thử một cái gì đó như thế này

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

4

Đây thực sự là hữu ích

SET search_path TO schema,public;

Tôi đã đào sâu vấn đề này nhiều hơn và tìm hiểu về cách đặt "search_path" này bằng cách gỡ rối cho một người dùng mới trong cơ sở dữ liệu hiện tại.

Mở Thuộc tính DataBase sau đó mở Bảng "Biến" và chỉ cần thêm biến này cho người dùng của bạn với giá trị thực.

Vì vậy, bây giờ người dùng của bạn sẽ nhận được tên_bảng này bằng cách gỡ rối và bạn có thể sử dụng tên bảng mà không cần lược đồ.


4

Bạn phải viết tên lược đồ và tên bảng trong dấu qutotation. Như sau:

select * from "schemaName"."tableName";

1

Đối với tôi, vấn đề là, tôi đã sử dụng một truy vấn tới bảng cụ thể đó trong khi Django được khởi tạo. Tất nhiên sau đó nó sẽ đưa ra một lỗi, bởi vì các bảng đó không tồn tại. Trong trường hợp của tôi, đó là một get_or_createphương thức trong tệp admin.txt, được thực thi bất cứ khi nào phần mềm chạy bất kỳ loại hoạt động nào (trong trường hợp này là di chuyển). Hy vọng rằng sẽ giúp được ai đó.


0

Bạn phải thêm lược đồ đầu tiên, vd

SELECT * FROM place.user_place;

Nếu bạn không muốn thêm nó vào tất cả các truy vấn thì hãy thử điều này:

SET search_path TO place;

Bây giờ nó sẽ hoạt động:

SELECT * FROM user_place;

0

Cách giải quyết dễ nhất là Chỉ cần thay đổi tên bảng và tất cả các tên cột thành chữ thường và vấn đề của bạn sẽ được giải quyết.

Ví dụ:

  • Thay đổi Table_Namethành table_name
  • Thay đổi ColumnNamethànhcolumnname
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.