You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP调用PostgreSQL时强制表名小写致表不存在问题求助

嘿,这个问题我太熟了!PostgreSQL的标识符大小写规则经常坑到不少人,我来给你拆解一下问题出在哪,以及怎么解决。

问题根源:PostgreSQL的标识符大小写规则

PostgreSQL对表名、列名这类标识符的处理逻辑很特殊:

  • 如果创建表的时候没有用双引号包裹表名(比如CREATE TABLE public.MSysQueries1),PostgreSQL会自动把表名转为全小写,实际存储的表名是msysqueries1
  • 但如果创建表的时候用了双引号(比如CREATE TABLE public."MSysQueries1"),表名会严格保留大小写,此时查询的时候必须也用双引号包裹表名,否则PostgreSQL会再次把表名转为小写,导致找不到你实际存在的那个带大写的表。

你遇到的报错relation "public.msysqueries1" does not exist,就是因为查询时PostgreSQL把你传入的MSysQueries1自动转成了全小写的msysqueries1,但你的数据库里实际是大小写敏感的MSysQueries1表。

解决方案:正确处理标识符(表名)

你需要做的核心操作是:把表名用双引号包裹起来传给PostgreSQL,同时要确保转义表名里的特殊字符(比如双引号),避免SQL注入或者语法错误。

推荐方案:使用pg_escape_identifier()

PHP从5.4版本开始提供了专门用于转义PostgreSQL标识符的函数pg_escape_identifier(),它会自动帮你完成两件事:给标识符加上双引号,以及转义标识符里的特殊字符(比如双引号会被转成两个双引号)。

修改后的代码如下:

$whatever = $_POST['tableID'];
$table2string = (string)$whatever;
// 用专门的标识符转义函数处理表名
$escapedTable = pg_escape_identifier($table2string);
$db = pg_connect("host=localhost port=5432 dbname=name user=user password=password");
// 直接拼接即可,$escapedTable已经被正确包裹双引号
$query = "SELECT * FROM public.$escapedTable;";
$result = pg_query($db, $query);

兼容旧版本PHP的方案

如果你的PHP版本低于5.4,没有pg_escape_identifier()函数,可以手动处理:

$whatever = $_POST['tableID'];
$table2string = (string)$whatever;
// 手动转义表名中的双引号(PostgreSQL要求用两个双引号表示一个)
$escapedTable = str_replace('"', '""', $table2string);
// 给表名加上双引号
$quotedTable = "\"$escapedTable\"";
$db = pg_connect("host=localhost port=5432 dbname=name user=user password=password");
$query = "SELECT * FROM public.$quotedTable;";
$result = pg_query($db, $query);
验证一下

你可以先输出最终生成的SQL语句看看,比如加一行echo $query;,正确的SQL应该是SELECT * FROM public."MSysQueries1";,这样PostgreSQL就能准确找到你的表了。

内容的提问来源于stack exchange,提问作者J. Sax

火山引擎 最新活动