sql 分配给变量在执行过程时不能 printed/queried
sql assigned to a variable couldn't be printed/queried when executing a procedure
DECLARE @DROP_SQL NVARCHAR(MAX)
DECLARE @create_Sql NVARCHAR(MAX)
DECLARE @tablename2 NVARCHAR(MAX)
DECLARE @insert_sql NVARCHAR(MAX)
DECLARE @db_schema NVARCHAR(MAX)
SET @db_schema='GGW'
SET @tablename2='VIEW_LOG'
DECLARE @count INT
SET @count=1
DECLARE @StartTime DATETIME
DECLARE @EndTime DATETIME
SET @StartTime =GETDATE()
SET @EndTime=GETDATE()
DECLARE @schema_nm NVARCHAR(MAX)
SET @schema_nm='GW'
DECLARE @tablename NVARCHAR(MAX)
SET @tablename='x'
SET @drop_sql = 'DROP TABLE IF EXISTS [GW].['+@tablename2+']'
PRINT @drop_sql
EXEC(@drop_sql)
SET @create_Sql = 'CREATE TABLE [GGW].[VIEW_LOG] (
schema_name NVARCHAR(MAX),
view_name NVARCHAR(max)
,row_count INT
,error_msg NVARCHAR(max)
,query_start_time DATETIME
,query_end_time DATETIME
,execution_time_in_ms NVARCHAR(max)
);'
PRINT @create_Sql
EXEC(@create_Sql)
SET @insert_sql='INSERT INTO ['+@db_schema+'].['+@tablename2+'] SELECT '+ @schema_nm+','+@tablename+','+CONVERT(NVARCHAR,@count)+','+NULL+','+CONVERT(VARCHAR, @StartTime)+','+CONVERT(VARCHAR, @EndTime)+','+CONVERT(VARCHAR, DATEDIFF(ms,@StartTime,@EndTime))
PRINT(@insert_sql)
EXEC(@insert_sql)
我创建了一个 table 并尝试将一些记录插入 table。 insert 语句被分配给一个变量,即@insert_sql。我正在尝试执行我创建并分配给变量但无法打印或执行的 sql。我在这里遗漏了什么吗?
上面有很多错误...问题下的评论触及了为什么上面失败了,你将 NULL
连接到你的字符串,结果是 NULL
,我强调了更多下面和 SQL 的评论中。当然,您根本不应该使用该串联,而应该 parametrising 您的 parameters.
SQL 中也有很多不一致之处;对模式名称的不同引用,有些是硬编码的,有些则不是。我已将所有架构引用替换为 dbo
以避免不正确的假设。
我还注入了你的对象名称,其中有动态 SQL,安全地 QUOTENAME
。 '[' + @SomeVariable + ']'
不 注射安全;特别是当你给某人 2GB/~10 亿个字符来“玩”时。右括号 (]
) 可以像单引号 ('
) 一样轻松转义,并且使用 2GB 的数据,恶意的人可以字面上做什么他们想要的;您的代码是一个等待被利用的安全漏洞。
我对数据类型做了一些假设,我没有对此进行测试,但它至少应该让您更接近所需的行为。
DECLARE @DROP_SQL nvarchar(MAX),
@create_Sql nvarchar(MAX),
@tablename2 sysname,
@insert_sql nvarchar(MAX),
@db_schema sysname;
SET @db_schema = N'dbo';
SET @tablename2 = N'VIEW_LOG';
DECLARE @count int;
SET @count = 1;
DECLARE @StartTime datetime,
@EndTime datetime;
SET @StartTime = GETDATE();
SET @EndTime = GETDATE();
DECLARE @schema_nm sysname;
SET @schema_nm = 'dbo';
DECLARE @tablename sysname;
SET @tablename = 'x';
SET @DROP_SQL = 'DROP TABLE IF EXISTS ' + QUOTENAME(@db_schema) + N'.' + QUOTENAME(@tablename2) + N';';
--PRINT @drop_sql
EXEC sys.sp_executesql @SQL;
--This query wasn't dynamic, so there's no point making it dynamic.
--Though the data types are all wrong here, see the comments below, but I create it with more correct data types
/*
CREATE TABLE [dbo].[VIEW_LOG] (
schema_name NVARCHAR(MAX), --Should this really be sysname?
view_name NVARCHAR(max), --Should this really be sysname?
row_count INT,
error_msg NVARCHAR(max), --Is your error really likely to be 4,000 characters or more?
query_start_time DATETIME,
query_end_time DATETIME,
execution_time_in_ms NVARCHAR(max)); --If it's time in ms, why is this an nvarchar(MAX)? Stop (ab)using nvarchar(MAX)
*/
CREATE TABLE [dbo].[VIEW_LOG] (schema_name sysname,
view_name sysname,
row_count int,
error_msg nvarchar(4000),
query_start_time datetime,
query_end_time datetime,
execution_time_in_ms int);
--PRINT @db_schema
--PRINT @tablename2
DECLARE @CRLF nchar(2) = NCHAR(13) + NCHAR(10); --Let's add some whitespace and line breaks to this query
SET @insert_sql = N'INSERT INTO ' + QUOTENAME(@db_schema) + N'.' + QUOTENAME(@tablename2) + N' (schema_name, view_name, row_count, error_msg, query_start_time, query_end_time, execution_time_in_ms)' + @CRLF + N'VALUES(@schema_nm,@tablename,@count,NULL,@StartTime,@EndTime,DATEDIFF(ms,@StartTime,@EndTime));';
--PRINT(@insert_sql)
EXEC sys.sp_executesql @SQL,
N'@schema_nm sysname,@tablename sysname,@count int,@StartTime datetime,@EndTime datetime',
@schema_nm,
@tablename,
@count,
@StartTime,
@EndTime;
DECLARE @DROP_SQL NVARCHAR(MAX)
DECLARE @create_Sql NVARCHAR(MAX)
DECLARE @tablename2 NVARCHAR(MAX)
DECLARE @insert_sql NVARCHAR(MAX)
DECLARE @db_schema NVARCHAR(MAX)
SET @db_schema='GGW'
SET @tablename2='VIEW_LOG'
DECLARE @count INT
SET @count=1
DECLARE @StartTime DATETIME
DECLARE @EndTime DATETIME
SET @StartTime =GETDATE()
SET @EndTime=GETDATE()
DECLARE @schema_nm NVARCHAR(MAX)
SET @schema_nm='GW'
DECLARE @tablename NVARCHAR(MAX)
SET @tablename='x'
SET @drop_sql = 'DROP TABLE IF EXISTS [GW].['+@tablename2+']'
PRINT @drop_sql
EXEC(@drop_sql)
SET @create_Sql = 'CREATE TABLE [GGW].[VIEW_LOG] (
schema_name NVARCHAR(MAX),
view_name NVARCHAR(max)
,row_count INT
,error_msg NVARCHAR(max)
,query_start_time DATETIME
,query_end_time DATETIME
,execution_time_in_ms NVARCHAR(max)
);'
PRINT @create_Sql
EXEC(@create_Sql)
SET @insert_sql='INSERT INTO ['+@db_schema+'].['+@tablename2+'] SELECT '+ @schema_nm+','+@tablename+','+CONVERT(NVARCHAR,@count)+','+NULL+','+CONVERT(VARCHAR, @StartTime)+','+CONVERT(VARCHAR, @EndTime)+','+CONVERT(VARCHAR, DATEDIFF(ms,@StartTime,@EndTime))
PRINT(@insert_sql)
EXEC(@insert_sql)
我创建了一个 table 并尝试将一些记录插入 table。 insert 语句被分配给一个变量,即@insert_sql。我正在尝试执行我创建并分配给变量但无法打印或执行的 sql。我在这里遗漏了什么吗?
上面有很多错误...问题下的评论触及了为什么上面失败了,你将 NULL
连接到你的字符串,结果是 NULL
,我强调了更多下面和 SQL 的评论中。当然,您根本不应该使用该串联,而应该 parametrising 您的 parameters.
SQL 中也有很多不一致之处;对模式名称的不同引用,有些是硬编码的,有些则不是。我已将所有架构引用替换为 dbo
以避免不正确的假设。
我还注入了你的对象名称,其中有动态 SQL,安全地 QUOTENAME
。 '[' + @SomeVariable + ']'
不 注射安全;特别是当你给某人 2GB/~10 亿个字符来“玩”时。右括号 (]
) 可以像单引号 ('
) 一样轻松转义,并且使用 2GB 的数据,恶意的人可以字面上做什么他们想要的;您的代码是一个等待被利用的安全漏洞。
我对数据类型做了一些假设,我没有对此进行测试,但它至少应该让您更接近所需的行为。
DECLARE @DROP_SQL nvarchar(MAX),
@create_Sql nvarchar(MAX),
@tablename2 sysname,
@insert_sql nvarchar(MAX),
@db_schema sysname;
SET @db_schema = N'dbo';
SET @tablename2 = N'VIEW_LOG';
DECLARE @count int;
SET @count = 1;
DECLARE @StartTime datetime,
@EndTime datetime;
SET @StartTime = GETDATE();
SET @EndTime = GETDATE();
DECLARE @schema_nm sysname;
SET @schema_nm = 'dbo';
DECLARE @tablename sysname;
SET @tablename = 'x';
SET @DROP_SQL = 'DROP TABLE IF EXISTS ' + QUOTENAME(@db_schema) + N'.' + QUOTENAME(@tablename2) + N';';
--PRINT @drop_sql
EXEC sys.sp_executesql @SQL;
--This query wasn't dynamic, so there's no point making it dynamic.
--Though the data types are all wrong here, see the comments below, but I create it with more correct data types
/*
CREATE TABLE [dbo].[VIEW_LOG] (
schema_name NVARCHAR(MAX), --Should this really be sysname?
view_name NVARCHAR(max), --Should this really be sysname?
row_count INT,
error_msg NVARCHAR(max), --Is your error really likely to be 4,000 characters or more?
query_start_time DATETIME,
query_end_time DATETIME,
execution_time_in_ms NVARCHAR(max)); --If it's time in ms, why is this an nvarchar(MAX)? Stop (ab)using nvarchar(MAX)
*/
CREATE TABLE [dbo].[VIEW_LOG] (schema_name sysname,
view_name sysname,
row_count int,
error_msg nvarchar(4000),
query_start_time datetime,
query_end_time datetime,
execution_time_in_ms int);
--PRINT @db_schema
--PRINT @tablename2
DECLARE @CRLF nchar(2) = NCHAR(13) + NCHAR(10); --Let's add some whitespace and line breaks to this query
SET @insert_sql = N'INSERT INTO ' + QUOTENAME(@db_schema) + N'.' + QUOTENAME(@tablename2) + N' (schema_name, view_name, row_count, error_msg, query_start_time, query_end_time, execution_time_in_ms)' + @CRLF + N'VALUES(@schema_nm,@tablename,@count,NULL,@StartTime,@EndTime,DATEDIFF(ms,@StartTime,@EndTime));';
--PRINT(@insert_sql)
EXEC sys.sp_executesql @SQL,
N'@schema_nm sysname,@tablename sysname,@count int,@StartTime datetime,@EndTime datetime',
@schema_nm,
@tablename,
@count,
@StartTime,
@EndTime;