在不运行查询的情况下进行 PostgreSQL 语法检查

问题描述 投票:0回答:8

我想验证包含 sql 查询的文件的语法,然后才能将其提交到我的 CVS 项目中。

为了做到这一点,我有一个 commitinfo 脚本,但我无法确定 sql 命令是否有效。

psql
似乎没有 dryrun 模式,并且从语法(位于源代码中)构建我自己的 postgresql-dialact 测试器似乎是一个漫长的过程。

脚本可能包含多个查询,因此

EXPLAIN
不能包含在它们周围。

有什么提示吗?

sql parsing postgresql syntax cvs
8个回答
61
投票

我最近编写了一个实用程序来静态检查 PostgreSQL 的 SQL 语法。它利用 ecpg(postgres 的嵌入式 SQL C 预处理器)来检查 SQL 语法,因此它使用与 Postgres 本身内置的完全相同的解析器。

您可以在 github 上查看:http://github.com/markdrago/pgsanity。您可以浏览一下自述文件,以更好地了解它的工作原理并获取如何安装它的说明。这是如何使用 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"

46
投票

使用这个技巧来验证 PostgreSQL 代码语法:

DO $SYNTAX_CHECK$ BEGIN RETURN;
    -- insert your SQL code here
END; $SYNTAX_CHECK$;

函数is_sql(sql文本)(链接到我的GitHub)


15
投票

一种方法是将其放入最后回滚的事务中:

BEGIN;
<query>;
<query>;
<query>;
ROLLBACK;

请注意,有些效果无法回滚,例如 dblink 调用,或写入文件系统或增量序列的任何内容。

我建议克隆您的数据库以进行测试。


11
投票

EXPLAIN(不带 ANALYZE)将解析查询并准备执行计划,但不实际执行它。

https://www.postgresql.org/docs/current/static/sql-explain.html


7
投票

我通常使用Mimer在线SQL验证器,唯一的事情是它检查标准SQL的SQL语法:

  • SQL-92
  • SQL-99
  • SQL-03

并不是特定于 PostgreSQL ...但是,如果您按照标准编写代码,则可以使用它并且它运行良好...


6
投票

验证 SQL 语法的绝佳实用程序:SQL Fiddle

支持 MySQL、Oracle、PostgreSQL、SQLite、MS SQL。


1
投票

你可以把它包起来

SELECT 1 ( <your query> ) AS a WHERE 1 = 0;

验证会失败,但实际上不会执行。这是一个查询计划示例:

Result  (cost=0.00..0.01 rows=1 width=0)
  One-Time Filter: false

1
投票

您可以在 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;

另一个解决方案 -

plpgsql_check
扩展(在 github 上),pgpsql_lint 的下一个化身

© www.soinside.com 2019 - 2024. All rights reserved.