在 Postgres 中转义类似关键字的列名
Posted
技术标签:
【中文标题】在 Postgres 中转义类似关键字的列名【英文标题】:Escaping keyword-like column names in Postgres 【发布时间】:2011-11-30 20:57:15 【问题描述】:如果 Postgres 表中的列名为 year
,应该如何查看 INSERT
查询来设置该列的值?
例如:INSERT INTO table (id, name, year) VALUES ( ... );
在 year 字附近出现错误。
【问题讨论】:
【参考方案1】:为了安全起见:始终引用标识符!为此,您必须使用分隔标识符构建插入语句。
SQL 2003 指定分隔标识符应该用双引号 "
引用,如果标识符中出现双引号,则必须重复双引号。查看 BNF:
https://ronsavage.github.io/SQL/sql-2003-2.bnf.html#delimited%20identifier
这是引用标识符的 Java 代码:
static String delimited_identifier (String identifier)
return "\"" + identifier.replaceAll ("\"", "\"\"") + "\"";
这是构建插入的代码:
static String build_insert (String table, String[] columns)
StringBuilder sql = new StringBuilder ();
StringBuilder values = new StringBuilder ();
sql.append ("INSERT INTO ");
sql.append (delimited_identifier (table));
sql.append (" (");
int c = 0;
if (columns.length > 0)
sql.append (delimited_identifier (columns[c]));
values.append ("?");
for (++c; c < columns.length; c++)
sql.append (", ");
sql.append (delimited_identifier (columns[c]));
values.append (", ?");
sql.append (") VALUES (");
sql.append (values.toString ());
sql.append (")");
return sql.toString ();
例子:
String sql = build_insert ("Person", new String[]"First name", "Last name");
【讨论】:
@questionto42 没有必要区分两种情况。只需引用每个标识符。几乎不可能知道所有数据库的所有保留字。而且我不确定您所说的“反逗号”是什么意思。引用的正确字符是“双引号”("
)。 mysql 使用反引号 (`
) 违反了 SQL 标准。我的回答涵盖了正确的引用方式。
@questionto42 我不确定我是否理解。你想要我将评论移到答案中吗?
如果有类似“无需区分两种情况。只需引用每个标识符。几乎不可能知道所有数据库的所有保留字的介绍。我会更好地理解您的答案。 "
在这个问题上扔Java代码不仅没用,还很可怕……【参考方案2】:
如果您没有在任何字段/列中提供引号,则默认情况下 Postgres 将其小写。 Postgres 会在涉及到列名时跳过检查关键字。
在您的情况下,我认为在 columns
中添加引号不是强制性的。
但是如果你使用keywords
(由Postgres注册)作为Table
、Schema
、Function
或Trigger
等的名称,你必须使用双引号,或者你可以指定模式名称点连接。
假设,order 是 Postgres 注册的关键字。并且在某些情况下,您必须使用此关键字作为表名。
届时,Postgres 将允许您使用keywords
创建一个表。这就是 Postgres 的美妙之处。
要访问订单表,您必须使用双引号,或者您可以在表名之前使用架构名称。
例如
1.
select * from schema_name.order;
2.
select * from "order";
同样,您可以使用这种类型的组合。希望这会对你有所帮助。
【讨论】:
【参考方案3】:只需将year
括在双引号中即可避免将其解释为keyword:
INSERT INTO table (id, name, "year") VALUES ( ... );
来自documentation:
还有第二种标识符:分隔标识符或 带引号的标识符。它是由一个任意序列组成的 双引号 (") 中的字符。分隔标识符始终是 标识符,绝不是关键字。所以“select”可以用来指代一个 名为“select”的列或表,而未引用的选择将是 作为关键字,因此会在以下情况下引发解析错误 在需要表名或列名的地方使用。
【讨论】:
一些警告:如果没有引号,PostgreSQL 会将所有标识符折叠为小写。MyTable
、myTable
和 mytable
是一样的。 使用 引号,此折叠未完成。所以"MyTable"
与mytable
不再相同。
更好的是,避免使用reserved words 或混合大小写作为标识符,您将永远不必使用双引号或收到奇怪的错误消息。
@djjeck: ***.com/questions/1992314/…
@ErwinBrandstetter 问题是当你在一个已建立的项目上工作时。
@HoàngLong 是的。 update "user" set "password" = 'value...';
工作得很好......以上是关于在 Postgres 中转义类似关键字的列名的主要内容,如果未能解决你的问题,请参考以下文章