是否可以让 Postgres 拒绝使用其专有的 SQL 语言扩展的查询?
例如select a::int from b;
应该抛出错误,强制使用正确的转换,如 select cast(a as int) from b;
也许更重要的问题是是否可以编写所有 RDBMS 都支持的具有相同结果行为的 SQL?
最佳答案
PostgreSQL 没有这样的特性。即使它这样做了,它也不会帮助你很多,因为对 SQL 标准的解释各不相同,对标准语法和功能的支持各不相同,而且一些数据库对其他人强制执行的限制或有其他人没有的限制有所放松。语法是你的问题中最少的。
编写跨数据库可移植 SQL 的唯一可靠方法是在每个目标数据库上测试该 SQL 作为自动化测试套件的一部分。并且经常发誓。
在许多地方,查询解析器/重写器将查询的标准“拼写”转换为 PostgreSQL 内部形式,这将在转储/重新加载时发出。特别是,PostgreSQL 不存储 View 、检查约束表达式、索引表达式等内容的原始源代码。它存储内部解析树,并在要求转储或显示对象时从中重建源代码。
例如:
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 委员会有另一个大脑放屁并拉一些时添加特殊情况功能新的创造性语法位...某处。改变它需要添加大量新的表达式节点类型和一般的困惑,所有这些都没有真正的好处。
关于sql - PostgreSQL 强制标准 SQL 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20831395/