数据库教程26:SQL Server中获取动态SQL的结果到变量中如何实现?

1,519 阅读3分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

下面是对执行动态SQL的介绍,如有需要,可直接查看使用sp_executesql传入传出参数,获取动态SQL的执行结果即可

动态SQL的执行通常是通过拼接符合SQL语法的字符串,从而可以根据执行过程中的条件,动态的完成对SQL语句的执行。

执行动态SQL很简单,重要的是,如何获取动态SQL的执行结果,这在某些情况下会很有用。

在实际开发中,我们经常用到动态SQL,通过不同的参数或变量,将其与其他的SQL命令拼接为一个完整的SQL语句,然后动态的执行该SQL字符串,实现想要的功能或获取数据。

而如何获取动态SQL的执行结果到一个变量中?以备进一步处理,则可以通过执行sp_executesql存储过程实现。

execute执行动态SQL

EXECEXECUTE 命令,通过函数调用形式传入SQL字符串,动态执行。

一个动态SQL示例

如下是一个简单的执行SQL字符串的动态SQL:

execute ('select * from Person.Address where city like ''a%'';');

结果如下:

获取数据库中包含某个列名的所有表

如下,获取数据库中某个列名,或者列名中包含某个字符串的所有表。

-- 获取数据库中包含某个列名的所有表
declare @colName varchar(30)='person';
declare @allContainer bit=0;	-- 列名全包含

declare @sqlStr varchar(500)='SELECT s.name as schema_names, t.name as table_names, col.name as col_names    
   FROM sys.objects AS t  
   JOIN sys.schemas AS s ON s.schema_id = t.schema_id
   JOIN sys.columns AS col ON col.object_id=t.object_id
   WHERE t.type = ''U'' AND col.name';

if @allContainer=1
begin
	select @sqlStr=@sqlStr+'='''+@colName+''';';
end
else
begin
	select @sqlStr=@sqlStr+' LIKE ''%'+@colName+'%'';';
end
exec (@sqlStr);

exec或execute执行动态SQL字符串时,必须将其放在()括号中。否则会将其视为存储过程或函数等,导致报错。

is not a valid identifier.

执行如下。

还可以据此进一步扩展,获取对应表中该列满足某条件的记录。

获取包含某列的所有表,参考自微软官方文档的示例:使用游标获取所有用户定义的表,并重建表的所有索引:

DECLARE tables_cursor CURSOR  
   FOR  
   SELECT s.name, t.name   
   FROM sys.objects AS t  
   JOIN sys.schemas AS s ON s.schema_id = t.schema_id  
   WHERE t.type = 'U';  
OPEN tables_cursor;  
DECLARE @schemaname sysname;  
DECLARE @tablename sysname;  
FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;  
WHILE (@@FETCH_STATUS <> -1)  
BEGIN;  
   EXECUTE ('ALTER INDEX ALL ON ' + @schemaname + '.' + @tablename + ' REBUILD;');  
   FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;  
END;  
PRINT 'The indexes on all tables have been rebuilt.';  
CLOSE tables_cursor;  
DEALLOCATE tables_cursor;  

使用sp_executesql向动态SQL中传入传出变量

sp_executesql存储过程用来执行可重复使用或动态构建的T-SQL语句或批处理。T-SQL语句或批处理可以包含嵌入式参数,也可以输入或输出数据。

语法如下:

sp_executesql [ @stmt = ] statement  
[   
  { , [ @params = ] N'@parameter_name data_type [ OUT | OUTPUT ][ ,...n ]' }   
     { , [ @param1 = ] 'value1' [ ,...n ] }  
]  

sp_executesql嵌入式参数的使用

sp_executesql向SQL语句传入参数,获取数据库中包含某个列名的所有表

declare @colName varchar(30)='person';
declare @allContainer bit=0;	-- 列名全包含
DECLARE @ParmDefinition NVARCHAR(500);  

SELECT @ParmDefinition='@colName varchar(30)';

declare @sqlStr nvarchar(500)='SELECT s.name as schema_names, t.name as table_names, col.name as col_names    
   FROM sys.objects AS t  
   JOIN sys.schemas AS s ON s.schema_id = t.schema_id
   JOIN sys.columns AS col ON col.object_id=t.object_id
   WHERE t.type = ''U'' AND col.name';

if @allContainer=1
begin
	select @sqlStr=@sqlStr+'=@colName';
end
else
begin
	select @sqlStr=@sqlStr+' LIKE ''%''+@colName+''%'';';
end
exec sp_executesql @sqlStr,@ParmDefinition,@colName=@colName;

动态SQL语句传入传出参数

sp_executesql中还可以使用output参数,实现从动态SQL中传出数据到某个变量中:

declare @colName varchar(30)='person';
declare @count int;
declare @allContainer bit=0;	-- 列名全包含
DECLARE @ParmDefinition NVARCHAR(500);  

SELECT @ParmDefinition='@colName varchar(30),@cnt int output';

declare @sqlStr nvarchar(500)='SELECT @cnt=count(*)    
   FROM sys.objects AS t  
   JOIN sys.schemas AS s ON s.schema_id = t.schema_id
   JOIN sys.columns AS col ON col.object_id=t.object_id
   WHERE t.type = ''U'' AND col.name';

if @allContainer=1
begin
	select @sqlStr=@sqlStr+'=@colName';
end
else
begin
	select @sqlStr=@sqlStr+' LIKE ''%''+@colName+''%'';';
end
exec sp_executesql @sqlStr,@ParmDefinition,@colName=@colName,@cnt= @count output;
select @count;