使用 EXPLAIN 命令验证 CREATE TABLE DDL 的语法
Validate syntax of CREATE TABLE DDLs using EXPLAIN Command
我有一些创建 table 脚本需要在我的应用程序中预先验证。我可以想到两种方法:
- 使用该脚本创建 table 并立即删除 table。
- 使用 EXPLAIN 命令查找语法错误而不创建它。
我发现第二种方法更有效。因此,我使用 Explain 命令验证了 CREATE TABLE DDL。
工作:
Teradata
Explain <CREATE TABLE DDL>
甲骨文
EXPLAIN PLAN FOR <CREATE TABLE DDL>
不工作:
SQL 服务器
Could not find stored procedure 'explain'.
SQLState: S00062
ErrorCode: 2812
Netezza
^ found "CREATE" (at char 18) expecting DELETE' or
INSERT' or SELECT' or
UPDATE' or `WITH'
DB2
Error: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=TABLE;EXPLAIN CREATE ;JOIN, DRIVER=4.14.111
SQLState: 42601
ErrorCode: -104
是否有任何其他更好的方法来验证创建 Table DDL?
是否有通用的方法来跨流行的 RDBMS 处理此问题?
如果解释是唯一可用的解决方案,如何对SQL Server、Netezza 和DB2 执行解释?
编辑:
这里validate的意思是检查语法(存储大小、精度、标度范围违规、保留关键字如table或列名等)
例如,查询如 -
create table abc (c1 decimal(555,44))
我想事先得到精度溢出错误。
您应该能够使用仅格式选项 SET FMTONLY ON
在 SQL 服务器中评估查询的正确性。设置此选项 SQL 服务器实际上不会尝试创建表。使用您的示例,T-SQL 将如下所示:
SET FMTONLY ON
create table abc (c1 decimal(555,44))
SET FMTONLY OFF
执行上述 T-SQL 将 return 错误消息“列或参数 #1:指定的列精度 555 大于最大精度 38。”
您还可以创建一个存储过程,使用最适合您所用数据库平台的方法为您评估查询。我不熟悉 Netezza、Teradata 和 DB2,但我假设它们可以执行动态 SQL。使用此方法,您只需将要评估的查询作为参数从应用程序层传递给存储过程。
以下代码片段显示了如何为 SQL 服务器完成此操作:
CREATE PROCEDURE ValidateQuerySyntax
(
@query NVARCHAR(MAX)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @validationQuery NVARCHAR(MAX) = 'SET FMTONLY ON; ' + CHAR(13) + @query + ';' + CHAR(13) + 'SET FMTONLY OFF;';
BEGIN TRY
EXEC (@validationQuery);
-- Return error code 0 if query validation was successful.
SELECT
0 AS ErrorNumber
,0 AS ErrorSeverity
,0 AS ErrorState
,0 AS ErrorLine
,'Query evaluated successfully' AS ErrorMessage;
END TRY
BEGIN CATCH
-- Return error information if query validation failed.
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
END
可以按如下方式评估查询:
DECLARE @query_1 NVARCHAR(MAX) =
'CREATE TABLE A
(
c1 INT
)';
DECLARE @query_2 NVARCHAR(MAX) =
'CREATE TABLE B
(
c1 INT
c2 INT
)';
DECLARE @query_3 NVARCHAR(MAX) =
'CREATE TABLE B
(
c1 INT
,c2 DECIMAL(555,44)
)';
EXEC dbo.ValidateQuerySyntax @query = @query_1;
EXEC dbo.ValidateQuerySyntax @query = @query_2;
EXEC dbo.ValidateQuerySyntax @query = @query_3;
上述验证调用的输出如下:
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ErrorNumber | ErrorSeverity | ErrorState | ErrorLine | ErrorMessage
-------------------------------------------------------------------------------------------------------------------------------------------------------------
0 | 0 | 0 | 0 | Query evaluated successfully
-------------------------------------------------------------------------------------------------------------------------------------------------------------
102 | 15 | 1 | 4 | Incorrect syntax near 'c2'.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
2750 | 16 | 1 | 1 | Column or parameter #2: Specified column precision 555 is greater than the maximum precision of 38.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
当然这确实意味着创建存储过程来首先为您评估查询,但它应该简化跨不同数据库平台的查询验证。
可能是 SQL PREPARE 语句,针对作为 DDL 语句的字符串发出;当 DDL CREATE TABLE 语句无效时,应该显示 SQLCODE 和 SQLSTATE。类似于以下类似 REXX 的伪代码:
sCrtTable="create table abc (c1 decimal(555,44))" ;
prepare DDL_stmt from :sCrtTable ;
say sqlCode ":" sqlState ; /* e.g.: "-604 : 42611" per invalid length attribute */
没有 generic/standard 方法适用于所有 DBMS。
我希望所有流行的 DBMS 都有类似于 EXPLAIN
命令的东西。 return 执行计划而不是 运行 查询本身。每个服务器都有自己的处理方式。
http://use-the-index-luke.com/sql/explain-plan 显示了如何为少数 DBMS 执行此操作。搜索 <your DBMS name> explain plan command
通常会得到很好的结果。
- DB2 -
EXPLAIN PLAN FOR
- SQL基础 -
SET PLANONLY ON
- MySQL -
EXPLAIN
- 甲骨文 -
EXPLAIN PLAN FOR
- PostgreSQL -
EXPLAIN
- SQL 服务器 -
SET SHOWPLAN_ALL ON
- Teradata -
EXPLAIN
- Netezza -
EXPLAIN VERBOSE
另一种方法是启动一个事务,运行 你的语句并回滚事务。当然,您需要有适当的错误处理,这又因服务器而异。在 SQL 服务器中有 TRY ... CATCH
。
还值得检查一下所选 DBMS 是否支持事务中的 DDL 语句。例如,在 MySQL "Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, those that create, drop, or alter tables or stored routines."
我对(至少)您的前两个问题的建议:
- 是否有任何其他更好的方法来验证创建 Table DDL?
- 是否有通用的方法来跨流行的 RDBMS 处理此问题?
将使用 Perl
的解析和数据库接口 capabilities/features(即 Perl DBI
模块)并编写一个脚本,通过准备好的语句验证 SQL反对您选择的数据库。
高级代码流为:
- 连接到您选择的数据库
- 运行 你的 SQL 通过
Perl
的 prepare()
电话(例如 $dbh->prepare('CREATE TABLE emp (emp_name VARCHAR2(30)')
- 检查
prepare()
调用的输出状态
prepare 调用准备要由数据库执行的查询。参数是任何 SQL 。在高端数据库上,prepare 会将 SQL 发送到数据库服务器,数据库服务器将对其进行编译。如果 prepare 成功,它 returns 一个代表该语句的语句句柄对象;否则它 return 是一个未定义的值,我们将中止该程序。 $dbh->errstr 将 return 失败的原因,这可能是“SQL 中的语法错误”。如果可能,它会从实际数据库中获取此原因。
Perl
还有一些其他模块值得一看,可能有用,即:
我有一些创建 table 脚本需要在我的应用程序中预先验证。我可以想到两种方法:
- 使用该脚本创建 table 并立即删除 table。
- 使用 EXPLAIN 命令查找语法错误而不创建它。
我发现第二种方法更有效。因此,我使用 Explain 命令验证了 CREATE TABLE DDL。
工作:
Teradata
Explain <CREATE TABLE DDL>
甲骨文
EXPLAIN PLAN FOR <CREATE TABLE DDL>
不工作:
SQL 服务器
Could not find stored procedure 'explain'. SQLState: S00062 ErrorCode: 2812
Netezza
^ found "CREATE" (at char 18) expecting
DELETE' or
INSERT' orSELECT' or
UPDATE' or `WITH'
DB2
Error: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=TABLE;EXPLAIN CREATE ;JOIN, DRIVER=4.14.111 SQLState: 42601 ErrorCode: -104
是否有任何其他更好的方法来验证创建 Table DDL?
是否有通用的方法来跨流行的 RDBMS 处理此问题?
如果解释是唯一可用的解决方案,如何对SQL Server、Netezza 和DB2 执行解释?
编辑:
这里validate的意思是检查语法(存储大小、精度、标度范围违规、保留关键字如table或列名等)
例如,查询如 -
create table abc (c1 decimal(555,44))
我想事先得到精度溢出错误。
您应该能够使用仅格式选项 SET FMTONLY ON
在 SQL 服务器中评估查询的正确性。设置此选项 SQL 服务器实际上不会尝试创建表。使用您的示例,T-SQL 将如下所示:
SET FMTONLY ON
create table abc (c1 decimal(555,44))
SET FMTONLY OFF
执行上述 T-SQL 将 return 错误消息“列或参数 #1:指定的列精度 555 大于最大精度 38。”
您还可以创建一个存储过程,使用最适合您所用数据库平台的方法为您评估查询。我不熟悉 Netezza、Teradata 和 DB2,但我假设它们可以执行动态 SQL。使用此方法,您只需将要评估的查询作为参数从应用程序层传递给存储过程。 以下代码片段显示了如何为 SQL 服务器完成此操作:
CREATE PROCEDURE ValidateQuerySyntax
(
@query NVARCHAR(MAX)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @validationQuery NVARCHAR(MAX) = 'SET FMTONLY ON; ' + CHAR(13) + @query + ';' + CHAR(13) + 'SET FMTONLY OFF;';
BEGIN TRY
EXEC (@validationQuery);
-- Return error code 0 if query validation was successful.
SELECT
0 AS ErrorNumber
,0 AS ErrorSeverity
,0 AS ErrorState
,0 AS ErrorLine
,'Query evaluated successfully' AS ErrorMessage;
END TRY
BEGIN CATCH
-- Return error information if query validation failed.
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
END
可以按如下方式评估查询:
DECLARE @query_1 NVARCHAR(MAX) =
'CREATE TABLE A
(
c1 INT
)';
DECLARE @query_2 NVARCHAR(MAX) =
'CREATE TABLE B
(
c1 INT
c2 INT
)';
DECLARE @query_3 NVARCHAR(MAX) =
'CREATE TABLE B
(
c1 INT
,c2 DECIMAL(555,44)
)';
EXEC dbo.ValidateQuerySyntax @query = @query_1;
EXEC dbo.ValidateQuerySyntax @query = @query_2;
EXEC dbo.ValidateQuerySyntax @query = @query_3;
上述验证调用的输出如下:
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ErrorNumber | ErrorSeverity | ErrorState | ErrorLine | ErrorMessage
-------------------------------------------------------------------------------------------------------------------------------------------------------------
0 | 0 | 0 | 0 | Query evaluated successfully
-------------------------------------------------------------------------------------------------------------------------------------------------------------
102 | 15 | 1 | 4 | Incorrect syntax near 'c2'.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
2750 | 16 | 1 | 1 | Column or parameter #2: Specified column precision 555 is greater than the maximum precision of 38.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
当然这确实意味着创建存储过程来首先为您评估查询,但它应该简化跨不同数据库平台的查询验证。
可能是 SQL PREPARE 语句,针对作为 DDL 语句的字符串发出;当 DDL CREATE TABLE 语句无效时,应该显示 SQLCODE 和 SQLSTATE。类似于以下类似 REXX 的伪代码:
sCrtTable="create table abc (c1 decimal(555,44))" ;
prepare DDL_stmt from :sCrtTable ;
say sqlCode ":" sqlState ; /* e.g.: "-604 : 42611" per invalid length attribute */
没有 generic/standard 方法适用于所有 DBMS。
我希望所有流行的 DBMS 都有类似于 EXPLAIN
命令的东西。 return 执行计划而不是 运行 查询本身。每个服务器都有自己的处理方式。
http://use-the-index-luke.com/sql/explain-plan 显示了如何为少数 DBMS 执行此操作。搜索 <your DBMS name> explain plan command
通常会得到很好的结果。
- DB2 -
EXPLAIN PLAN FOR
- SQL基础 -
SET PLANONLY ON
- MySQL -
EXPLAIN
- 甲骨文 -
EXPLAIN PLAN FOR
- PostgreSQL -
EXPLAIN
- SQL 服务器 -
SET SHOWPLAN_ALL ON
- Teradata -
EXPLAIN
- Netezza -
EXPLAIN VERBOSE
另一种方法是启动一个事务,运行 你的语句并回滚事务。当然,您需要有适当的错误处理,这又因服务器而异。在 SQL 服务器中有 TRY ... CATCH
。
还值得检查一下所选 DBMS 是否支持事务中的 DDL 语句。例如,在 MySQL "Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, those that create, drop, or alter tables or stored routines."
我对(至少)您的前两个问题的建议:
- 是否有任何其他更好的方法来验证创建 Table DDL?
- 是否有通用的方法来跨流行的 RDBMS 处理此问题?
将使用 Perl
的解析和数据库接口 capabilities/features(即 Perl DBI
模块)并编写一个脚本,通过准备好的语句验证 SQL反对您选择的数据库。
高级代码流为:
- 连接到您选择的数据库
- 运行 你的 SQL 通过
Perl
的prepare()
电话(例如$dbh->prepare('CREATE TABLE emp (emp_name VARCHAR2(30)')
- 检查
prepare()
调用的输出状态
prepare 调用准备要由数据库执行的查询。参数是任何 SQL 。在高端数据库上,prepare 会将 SQL 发送到数据库服务器,数据库服务器将对其进行编译。如果 prepare 成功,它 returns 一个代表该语句的语句句柄对象;否则它 return 是一个未定义的值,我们将中止该程序。 $dbh->errstr 将 return 失败的原因,这可能是“SQL 中的语法错误”。如果可能,它会从实际数据库中获取此原因。
Perl
还有一些其他模块值得一看,可能有用,即: