2014-10-29 109 views

回答

2

检查列名是否需要引用,方法是引用它们并将结果与​​原始值进行比较。

SELECT * from pg_attribute 
WHERE attname <> quote_ident(attname) 
     ; 

CREATE TABLE bad ("integer" integer not null primary key 
     , "where" TEXT NOT NULL 
     , "table" TEXT NOT NULL 
     , "as" TEXT NOT NULL 
     , "is" TEXT NOT NULL 
     , "primary" TEXT NOT NULL 
     , "references" TEXT NOT NULL 
     ); 

SELECT * from pg_attribute 
WHERE attname <> quote_ident(attname) 

DROP TABLE bad cascade; 

上面还会捕获MixedCaseIdentifiers。要取消这些,请使用:

CREATE TABLE mixed ("Mixed" integer not null primary key); 

SELECT * from pg_attribute 
WHERE lower(attname) <> quote_ident(lower(attname)) 
     ; 

DROP TABLE mixed cascade; 

但是,这也会捕获嵌入空格的标识符。为了捕捉这些,在比较之前将其删除:

CREATE TABLE spaced ("spa ced" integer not null primary key); 

SELECT * from pg_attribute 
WHERE lower(replace(attname, ' ' ,'')) 
    <> quote_ident(lower(replace(attname, ' ' ,''))) 
    ; 

相同的技巧,裹成一个SQL函数:

CREATE function check_needsquoting(str text) returns Boolean AS 
$func$ 
select lower(replace(str, ' ' ,'')) 
    <> quote_ident(lower(replace(str, ' ' ,''))) 
    ; 
$func$ LANGUAGE sql; 

SELECT check_needsquoting ('FooBar'); 
SELECT check_needsquoting ('where'); 
SELECT check_needsquoting ('create'); 

DROP function check_needsquoting(str text); 

结果:

CREATE FUNCTION 
check_needsquoting 
-------------------- 
f 
(1 row) 

check_needsquoting 
-------------------- 
t 
(1 row) 

check_needsquoting 
-------------------- 
t 
(1 row) 

DROP FUNCTION 

结合这个函数的结果来自通过@vyegorov提到功能)产量:

SELECT 
     kw.word, kw.catcode 
     , check_needsquoting(kw.word) AS needsquote 
from pg_get_keywords() kw 
ORDER BY kw.word 
     ; 

从而得出结论,只有catcode IN ('C', 'R')需要被引用。 注:pg_get_keywords()自Postgresql-8.4以来似乎可用。 (和quote_ident()至少 PostgreSQL相关7.2)


UPDATE:它出现在语法中使用的所有词语需要检测,不仅保留的:

CREATE function check_ifsyntaxword(str text) returns Boolean AS 
$func$ 
select EXISTS(
     select 1 
     from pg_get_keywords() kw 
     WHERE lower(kw.word) = lower(str) 
     ) 
    ; 
$func$ LANGUAGE sql; 
+0

事情是 - 标识符不仅仅是属性,而是所有其他类型的对象。 – vyegorov 2014-10-29 13:26:35

+0

是的,的确如此,这只是第一次努力。 IIRC,在postgres源代码中保留了一个保留字(关键字?)列表,我不知道它是否也作为(伪)表发布。会很整齐。注意:上面的片段捕获“整数”;我希望它抓住“哪里”,“作为”,“是”等。更新:我只是检查:它确实抓住了他们。 – wildplasser 2014-10-29 13:47:03

相关问题