这可能需要清理一些,但您可以通过使用存储在动态 SQL 中sys.objects
并sys.columns
与动态 SQL 一起使用的元数据来做到这一点。请注意,我不是动态 SQL 的粉丝,但出于报告目的,它应该不是太大的问题。
一些用于创建测试数据的 SQL:
if (object_id('test') is not null)
drop table test;
create table test
(
id uniqueidentifier not null default newId()
,col0 nvarchar(255)
,col1 nvarchar(255)
,col2 nvarchar(255)
,col3 nvarchar(255)
,col4 nvarchar(255)
);
insert into test (col0,col1,col2,col3,col4)
select 'alice','bob','charlie','dave','emily'
union
select 'abby','bill','charlotte','daniel','evan'
用于构建 CSV 行的存储过程:
-- emit the contents of a table as a CSV.
-- @table_name: name of a permanent (in sys.objects) table
-- @debug: set to 1 to print the generated query
create procedure emit_csv(@table_name nvarchar(max), @debug bit = 0)
as
declare @object_id int;
set nocount on;
set @object_id = object_id(@table_name);
declare @name nvarchar(max);
declare db_cursor cursor for
select name
from sys.columns
where object_id = @object_id;
open db_cursor;
fetch next from db_cursor into @name
declare @query nvarchar(max);
set @query = '';
while @@FETCH_STATUS = 0
begin
-- TODO: modify appended clause to escape commas in addition to trimming
set @query = @query + 'rtrim(cast('+@name+' as nvarchar(max)))'
fetch next from db_cursor into @name;
-- add concatenation to the end of the query.
-- TODO: Rearrange @query construction order to make this unnecessary
if (@@fetch_status = 0)
set @query = @query + ' + '','' +'
end;
close db_cursor;
deallocate db_cursor;
set @query = 'select rtrim('+@query+') as csvrow from '+@table_name;
if @debug != 0
begin
declare @newline nvarchar(2);
set @newline = char(13) + char(10)
print 'Generated SQL:' + @newline + @query + @newline + @newline;
end
exec (@query);
对于我的测试表,这会生成查询:
select
rtrim(rtrim(cast(id as nvarchar(max)))
+ ','
+rtrim(cast(col0 as nvarchar(max)))
+ ','
+rtrim(cast(col1 as nvarchar(max)))
+ ','
+rtrim(cast(col2 as nvarchar(max)))
+ ','
+rtrim(cast(col3 as nvarchar(max)))
+ ','
+rtrim(cast(col4 as nvarchar(max))))
as csvrow
from test
和结果集:
csvrow
-------------------------------------------------------------------------------------------
EEE16C3A-036E-4524-A8B8-7CCD2E575519,alice,bob,charlie,dave,emily
F1EE6C84-D6D9-4621-97E6-AA8716C0643B,abby,bill,charlotte,daniel,evan
建议
- 修改光标循环以转义逗号
- 确保 @table_name 引用存储过程中的有效表 (
if object_id(@table_name) is null
)
- 一些异常处理会很好
- 对此设置权限,以便只有运行报表的帐户才能执行它。动态 SQL 中的字符串连接可能是一个很大的安全漏洞,但我没有看到其他方法可以做到这一点。
- 确保游标关闭和释放的一些错误处理可能很好。
这可以用于任何不是表格的#temp
表格。在这种情况下,您必须使用sys.objects
and sys.columns
from tempdb..
。