这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战
下面是对执行动态SQL的介绍,如有需要,可直接查看使用sp_executesql传入传出参数,获取动态SQL的执行结果即可
动态SQL的执行通常是通过拼接符合SQL语法的字符串,从而可以根据执行过程中的条件,动态的完成对SQL语句的执行。
执行动态SQL很简单,重要的是,如何获取动态SQL的执行结果,这在某些情况下会很有用。
在实际开发中,我们经常用到动态SQL,通过不同的参数或变量,将其与其他的SQL命令拼接为一个完整的SQL语句,然后动态的执行该SQL字符串,实现想要的功能或获取数据。
而如何获取动态SQL的执行结果到一个变量中?以备进一步处理,则可以通过执行sp_executesql存储过程实现。
execute执行动态SQL
EXEC 或 EXECUTE 命令,通过函数调用形式传入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;