不要省略AS
列别名的关键字
SELECT id, left(first, 65535) first from "public"."MyTableName";
这会爆炸,因为首先作为列名需要用双引号引起来。
不完全是。它爆炸了,因为你省略了关键字AS
不应该被省略的地方。
这有效:
SELECT 'select '
|| string_agg(
case when udt_name in ('varchar', 'text')
then 'left(' || quote_ident(column_name) || ', 65535) AS ' -- !!
|| quote_ident(column_name)
else quote_ident(column_name)
end, ', ' order by ordinal_position)
|| ' from "public"."MyTableName"'
FROM information_schema.columns c
join parse_ident('"public"."MyTableName"') t
on t[1] = table_schema and t[2] = table_name;
生产:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
依次按预期工作。
The 手册关于“省略 AS 关键字”:
在SQL标准中,可选关键字AS
前面可以省略
每当新列名是有效列时输出列名
名称(即与任何保留关键字不同)。 PostgreSQL 是
限制性稍强一些:AS
如果新列名称是必需的
匹配任何关键字,无论是否保留。推荐的做法是
使用 AS 或双引号输出列名,以防止任何可能的
与将来添加的关键字冲突。
省略关键字就可以了AS
适用于表别名,但不适用于列别名。
first
不是一个保留字在 Postgres 中。 (它曾经在古老的 SQL 标准 SQL-92 中被“保留”,但在标准 SQL 中也不再被保留。)“非保留”* 准确地说。手册:
非保留关键字仅在特定上下文中具有特殊含义,并且可以在其他上下文中用作标识符。
省略AS
使它成为这样一个背景。
quote_ident()
工作可靠。手册:
返回适当引用的给定字符串以用作标识符
在 SQL 语句字符串中。仅在必要时添加引号(即
如果字符串包含非标识符字符或者将是
折叠盒)。嵌入的引号适当加倍。
format()
与说明符%I
做同样的事情。
未提及保留字,但无论如何都正确引用。准确的说:所有关键词都标注了“预订的” or “(不能是函数或类型)”在“PostgreSQL”列中the SQL关键字 table.
我将提交一个文档错误来添加它。
绝对确定的是:quote_all_identifiers
如果你想绝对确定并且不介意所有增加的噪音,你可以强制 Postgres 引用all带有配置参数的标识符quote_all_identifiers
. 手册:
当数据库生成 SQL 时,强制所有标识符都加引号,即使它们(当前)不是关键字。
这包括来自的输出quote_ident()
and format()
。我会not这样做,害怕所有增加的噪音。
您可以在本地设置参数SET LOCAL
在同一笔交易中。喜欢:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Faster
也就是说,我会用format()
and concat()
并定位目录表pg_attribute
相反:更干净、更简单、更快。但不能移植到其他 RDBMS:
SELECT format('SELECT %s FROM %s;'
, string_agg(CASE WHEN atttypid = ANY ('{text, bpchar, varchar}'::regtype[])
THEN concat('left(', col, ', 65535) AS ', col)
ELSE col END, ', ')
, attrelid)
FROM (
SELECT attrelid::regclass, atttypid, quote_ident(attname) AS col
FROM pg_catalog.pg_attribute
WHERE attrelid = 'public."MyTableName"'::regclass -- provide once, optionally schema-qualified
AND attnum > 0
AND NOT attisdropped
ORDER BY attnum
) sub
GROUP BY attrelid;
生产:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
数据库小提琴here
尤其, ...
- ...您只需提供一次表名,可以选择模式限定。
- ...如果该表不存在,查询会立即失败并显示一条有用的错误消息。
- ...输出表名称仅是模式限定的,并在必要时用双引号引起来。
- ...这也涵盖
character(N)
(内部名称bpchar
).
进一步阅读:
- 如何检查给定模式中是否存在表
- postgres psql select 语句中默认截断显示
- PostgreSQL 强制所有数据大写
- 检查字符类型列中是否存在空字符串