我正在尝试创建一个函数,该函数根据表名和列名参数返回以逗号分隔的值列表。
我们的想法是动态构建动态SQL语句,然后返回结果。但是,我遇到了一个问题,它不允许我在函数内部运行execute
语句。这就是我所拥有的:
ALTER FUNCTION fn_HearingAttendeesToCSV (@TableName varchar(100),
@ColumnName varchar(100))
RETURNS VARCHAR(MAX)
AS
BEGIN
declare @sql varchar(max)
select @sql =
'DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr + '', '' ,'''') + '
+ @ColumnName + ' FROM ' + @TableName + ' RETURN @listStr '
Exec (@sql)
END
GO
我很确定我走错了路。有人可以建议如何解决execute
问题吗?或者更好的方法呢?
答案 0 :(得分:3)
你不能在一个功能期间这样做。函数无法执行动态SQL,因此使用任意表/列名称(非确定性)都会面临SQL Server函数。
答案 1 :(得分:2)
您好我认为它们的功能正确,但您可以使用带输出参数的SP来执行此操作。
检查此代码:
create proc DynCsv
@table varchar(100),
@column varchar(100),
@csv varchar(8000) output
as
declare
@sql nvarchar(4000),
@parms nvarchar(100)
-- setup parms
select @csv = '',
@sql = '
select top 10 @csv = @csv +'','' + CAST(' + @column + ' as varchar)
from ' + @table + ' option(maxdop 1)',
@parms = '@csv varchar(8000) output'
-- execute dynamic
exec sp_executesql
@sql,
@parms,
@csv = @csv output
-- loose first comma
set @csv = substring(@csv, 2, 8000)
您可以使用以下代码调用它:
declare @csv varchar(8000)
exec dynCsv 'tObj', 'ObjId', @csv output
print @csv
祝你好运,
GJ
答案 2 :(得分:2)
我认为你不能通过T-SQL做到这一点,但你绝对可以通过用C#编写的UDF来完成同样的事情。这是代码:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions {
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
public static SqlString fn_HearingAttendeesToCSV(SqlString tableName, SqlString columnName) {
System.Text.StringBuilder result = null;
using (var cnn = new SqlConnection("context connection=true")) {
var cmd = new SqlCommand();
cmd.CommandText = String.Format("select [{0}] from [{1}]", SqlEscape(columnName.Value), SqlEscape(tableName.Value));
cmd.Connection = cnn;
cnn.Open();
using (var rdr = cmd.ExecuteReader()) {
while (rdr.Read()) {
if (result == null) {
result = new System.Text.StringBuilder();
}
else {
result.Append(",");
}
result.Append(CsvEscape(rdr[0]));
}
}
cnn.Close();
}
if (result == null) {
return SqlString.Null;
}
else {
return result.ToString();
}
}
private static string SqlEscape(string s) {
s = s ?? "";
return s.Replace("[", "[[").Replace("]", "]]");
}
private static string CsvEscape(object o) {
var s = o == null ? "" : o.ToString();
return "\"" + s.Replace("\"", "\"\"") + "\"";
}
};
要使用CLR UDF,您需要确保已在服务器上启用它们,如下所示:
exec sp_configure 'clr enabled', 1
RECONFIGURE
您还需要编译到旧版本的.NET框架(我测试的是2.0),因为SQL 2005不允许4.0程序集。
即使你的UDF是用C#编写的,你仍然可以像以前一样通过T-SQL访问它:
select fn_HearingAttendeesToCSV('table', 'column')
如果您需要支持“dbo”以外的架构,或者如果您不需要纯CSV,请修改以满足您的需求,但这应该可以让您获得99%的支持。也就是说,假设你是DBA,或者你和他/她有足够好的伙伴来启用CLR。
答案 3 :(得分:1)
你不能在函数中执行此操作,但可以在PROCEDURE中执行此操作。我已经多次完成了构建动态SQL语句。
这是要走的路。