提问人:Rob Audenaerde 提问时间:11/26/2011 最后编辑:Rob Audenaerde 更新时间:11/17/2023 访问量:78912
PostgreSQL 语法检查,无需运行查询
PostgreSQL syntax check without running the query
问:
我想先验证包含 sql 查询的文件的语法,然后才能在我的 CVS 项目中提交它们。
为了做到这一点,我有一个commitinfo脚本,但我很难确定sql命令是否有效。 似乎没有试运行模式,从语法(即源代码中)构建我自己的 postgresql-dialact 测试器似乎是一个很长的过程。psql
脚本可能包含多个查询,因此不能围绕它们进行包装。EXPLAIN
有什么提示吗?
答:
一种方法是将其放入最后回滚的事务中:
BEGIN;
<query>;
<query>;
<query>;
ROLLBACK;
请注意,有些效果是无法回滚的,例如 dblink 调用、写入文件系统的任何内容或递增的序列。
我建议克隆您的数据库以进行测试。
评论
BEGIN;
WARNING
我通常使用 Mimer 在线 SQL 验证器,唯一的问题是它检查标准 SQL 的 SQL 语法:
- SQL-92的
- SQL-99型
- SQL-03型
并且不特定于 PostgreSQL ...但是,如果您按照标准编写代码,则可以使用它并且运行良好......
评论
我最近写了一个实用程序来静态检查 PostgreSQL 的 SQL 语法。它利用 postgres 的嵌入式 SQL C preproccessor ecpg 来检查 SQL 语法,因此它使用与 Postgres 本身内置的完全相同的解析器。
您可以在 github 上查看:http://github.com/markdrago/pgsanity。您可以浏览 README,以更好地了解它的工作原理并获取有关如何安装它的说明。下面是一个如何使用 pgsanity 的简短示例:
$ pgsanity good1.sql good2.sql bad.sql
bad.sql: line 1: ERROR: syntax error at or near "bogus_token"
$ find -name '*.sql' | xargs pgsanity
./sql/bad1.sql: line 59: ERROR: syntax error at or near ";"
./sql/bad2.sql: line 41: ERROR: syntax error at or near "insert"
./sql/bad3.sql: line 57: ERROR: syntax error at or near "update"
评论
你可以把它包起来SELECT 1 ( <your query> ) AS a WHERE 1 = 0;
它会在验证时失败,但实际上不会执行。下面是一个示例查询计划:
Result (cost=0.00..0.01 rows=1 width=0)
One-Time Filter: false
评论
验证 SQL 语法的绝妙实用程序:SQL Fiddle
支持 MySQL、Oracle、PostgreSQL、SQLite、MS SQL。
EXPLAIN(不带 ANALYZE)将解析查询并准备执行计划,而不实际执行它。
https://www.postgresql.org/docs/current/static/sql-explain.html
评论
您可以在 postgresql 函数之外运行查询,并在最后引发异常。所有更改都将回滚。例如:
CREATE OR REPLACE FUNCTION run_test(_sp character varying)
RETURNS character varying AS
$BODY$
BEGIN
EXECUTE 'SELECT ' || _sp;
RAISE EXCEPTION '#OK';
EXCEPTION
WHEN others THEN
RETURN SQLERRM;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
另一个解决方案 - 扩展(在 github 上),pgpsql_lint 的下一个化身plpgsql_check
评论
使用此技巧验证 PostgreSQL 代码语法:
DO $SYNTAX_CHECK$ BEGIN RETURN;
-- insert your SQL code here
END; $SYNTAX_CHECK$;
函数 is_sql(sql text)(链接到我的 GitHub)
评论
commit;
commit
CREATE TABLE foo(id int); DO $$ BEGIN RETURN; BEGIN; INSERT INTO foo VALUES (1); COMMIT; END; $$; SELECT * FROM foo;
BEGIN
DO
DO $$ BEGIN RETURN; IF true THEN select 1; END IF; END; $$;
IF ... THEN ... END IF
ERROR: syntax error at or near "END"
SAVEPOINT my_savepoint; ...; ROLLBACK TO SAVEPOINT my_savepoint;
DO
上一个:分号作为 URL 查询分隔符
评论
PLPGSQL lint
感兴趣,它恰好解决了这个缺点。Pavel Stěhule 是主要开发者。请参阅此博客文章。