是否有可能让Postgres拒绝使用其SQL语言专有扩展的查询?
e.g。 select a::int from b;
应该抛出错误,强制使用select cast(a as int) from b;
或许更重要的是,是否有可能编写具有相同结果行为的所有RDBMS支持的SQL?
答案 0 :(得分:6)
PostgreSQL没有这样的功能。即使它确实如此,它也无济于事,因为对SQL标准的解释各不相同,对标准语法和功能的支持各不相同,而且有些DB对其他人强制执行的限制或其他人没有的限制感到放松。语法是你问题最少的。
编写跨数据库可移植SQL的唯一可靠方法是在每个目标数据库上测试该SQL作为自动测试套件的一部分。而且要发誓。
在许多地方,查询解析器/重写器将查询的标准“拼写”转换为PostgreSQL内部形式,这将在转储/重新加载时发出。特别是,PostgreSQL不存储视图,检查约束表达式,索引表达式等原始源代码。它存储内部分析树,并在要求转储或显示对象时重建源代码。< / p>
例如:
regress=> CREATE TABLE sometable ( x varchar(100) );
CREATE TABLE
regress=> CREATE VIEW someview AS SELECT CAST (x AS integer) FROM sometable;
CREATE VIEW
regress=> SELECT pg_get_viewdef('someview');
pg_get_viewdef
-------------------------------------
SELECT (sometable.x)::integer AS x
FROM sometable;
(1 row)
无论如何它都是无用的,因为标准没有指定一些非常常见和重要的功能,并且通常对它确定的事物有相当模糊的规范。直到最近它还没有定义限制查询返回的行数的方法,例如,因此每个数据库都有自己不同的语法(TOP
,LIMIT
/ OFFSET
,等)。
大多数供应商都没有实现标准规定的其他内容,因此使用它们是毫无意义的。祝所有数据库供应商使用SQL标准生成和标识列,祝你好运。
有一个“首选标准拼写”转储模式,使用CAST
而不是::
等等,这是非常好的,但它真的不是很简单,因为有些转换不是1:1可逆,例如:
regress=> CREATE VIEW v AS SELECT '1234' SIMILAR TO '%23%';
CREATE VIEW
regress=> SELECT pg_get_viewdef('v');
SELECT ('1234'::text ~ similar_escape('%23%'::text, NULL::text));
或:
regress=> CREATE VIEW v2 AS SELECT extract(dow FROM current_date);
CREATE VIEW
regress=> SELECT pg_get_viewdef('v2');
SELECT date_part('dow'::text, ('now'::text)::date) AS date_part;
因此,您会发现需要对PostgreSQL内部表示的方式进行重大更改,并在您想要之前使用函数和表达式。
许多SQL标准的东西使用了时髦的一次性语法,PostgreSQL在解析过程中转换为函数调用和强制转换,因此每次SQL委员会有另一个脑屁时都不需要添加特殊的案例功能某个地方出现了新的创造性语法。改变这将需要添加大量新的表达式节点类型和一般混乱,所有这些都没有真正的好处。
答案 1 :(得分:3)
或许更重要的是是否可能的问题 编写具有相同结果的所有RDBMS支持的SQL 行为?
不,即使是很多简单的陈述......
select top 10 ... -- tsql
select ... limit 10 -- everyone else
存在更多的例子。如果你想让自己与数据库选择隔离,请使用orm或类似的东西。
如果你手工编写sql,那么尝试遵循SQL标准总是一个不错的选择:-)
答案 2 :(得分:1)
您可以使用Mimer的SQL Validator之类的工具在运行之前验证查询是否符合SQL规范: