我知道,对于PostgreSQL中的文本字符串,通过在文本前添加符号E
或e
来统一换行符。
SELECT E'first\nsecond'
结果:
first
second
但PostgreSQL也支持列名中的换行符 - 不确定这种做法为何或如何邪恶,但可以做到以下几点:
CREATE TABLE One("first\nsecond" text);
CREATE TABLE Two("first
second" text);
当你不幸碰到其中一个时,你会发现这些查询有效:
SELECT "first\nsecond" from One;
SELECT "first
second" from Two;
这些不是:
SELECT "first
second" from One;
SELECT "first\nsecond" from Two;
我的问题是:PostgreSQL中是否有一种方法可以统一这些差异,类似于列值的情况?
我尝试将E
放在"first\nsecond"
列名称前面,但不支持。试图改为放置\r\n
(我使用的是Windows)给了我第三种类型的列名,只能查询为:
SELECT "first\r\nsecond" FROM Third
答案 0 :(得分:4)
列名称是标识符,标识符语法的血淋淋的细节描述于:
http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
TL; DR :使用U&"..."
语法通过Unicode代码点将不可打印的字符注入标识符,并且无法将CR,LF
与{{1}统一单独。
我们被允许在标识符中使用Unicode转义序列,因此根据文档,以下内容确实有效:
LF
如果它只是两个单词之间的换行符。
该表创建于:
select U&"first\000asecond" from Two;
由于反斜杠字符在此处没有特殊含义,因此该列不包含任何换行符。
它包含CREATE TABLE One("first\nsecond" text);
,后跟first
,后跟\
,后跟n
。
所以:
second
确实有效,因为它与 SELECT "first\nsecond" from One;
,而
CREATE TABLE
失败,因为SELECT中有一个换行符,表中的实际列名称后跟一个反斜杠后跟SELECT "first
second" from One;
。
这与“一”相反。
n
换行符是逐字记录的,也是专栏的一部分。 所以
CREATE TABLE Two("first
second" text);
有效,因为换行符与CREATE TABLE完全相同, 嵌入式换行符, 而
SELECT "first
second" from Two;
失败,因为之前SELECT "first\nsecond" from Two;
在此上下文中并不代表换行符。
正如评论和编辑中所提到的,这可能是回车和换行,在这种情况下,应该做以下事情:
\n
虽然在我的测试中,在Unix和Windows上使用select U&"first\000d\000asecond" from Two;
在列的中间点击Enter具有相同的效果:列名称中有一个换行符。
要检查列名中最终的确切字符,我们可以用十六进制检查它们。
当应用于你的create table示例时,来自Unix下的psql内部:
psql
结果是:
CREATE TABLE Two("first
second" text);
select convert_to(column_name::text,'UTF-8')
from information_schema.columns
where table_schema='public'
and table_name='two';
对于更复杂的情况(例如,UTF-8中包含多个字节的非ascii字符),对于易于阅读的代码点,更高级的查询可能会有所帮助:
convert_to
----------------------------
\x66697273740a7365636f6e64