Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 如何使用动态SQL从func/sp获取case语句的值?_Sql Server 2008_Function_Stored Procedures_Dynamic Sql_Case Statement - Fatal编程技术网

Sql server 2008 如何使用动态SQL从func/sp获取case语句的值?

Sql server 2008 如何使用动态SQL从func/sp获取case语句的值?,sql-server-2008,function,stored-procedures,dynamic-sql,case-statement,Sql Server 2008,Function,Stored Procedures,Dynamic Sql,Case Statement,希望有人能帮我解决一些问题。基本上,我试图获得数据库中所有字段的大致大小,因为我想对其进行一些数学运算,以猜测应用压缩技术后的大小 对于大多数字段,我可以通过查看数据类型并使用行数来获取它占用的字节数来实现这一点。然而,对于像varchar(max)字段这样的字段,这并不容易,因此我决定通过获取列中的平均长度并乘以行数来实现这一点。但我遇到了一个障碍,我将在下面描述 我有以下存储过程(我也尝试了一个函数,但不能从函数调用动态SQL) 创建过程dbo.getFieldSize(@column v

希望有人能帮我解决一些问题。基本上,我试图获得数据库中所有字段的大致大小,因为我想对其进行一些数学运算,以猜测应用压缩技术后的大小

对于大多数字段,我可以通过查看数据类型并使用行数来获取它占用的字节数来实现这一点。然而,对于像varchar(max)字段这样的字段,这并不容易,因此我决定通过获取列中的平均长度并乘以行数来实现这一点。但我遇到了一个障碍,我将在下面描述

我有以下存储过程(我也尝试了一个函数,但不能从函数调用动态SQL)


创建过程dbo.getFieldSize(@column varchar(255),@table varchar(255),@ret decimal(15,7)输出)
像
开始
声明@lengthSQL varchar(50)
/SET@lengthSQL='从['+@table+']中选择@ret=AVG(DATALENGTH('+@column+'))/
SET@lengthSQL='从'+@表中选择@ret=AVG(DATALENGTH(+@column++')
exec sp_executesql@lengthSQL
返回@ret
终止
去

然后我用


选择b.TABLE_SCHEMA作为“SCHEMA”,
当数据_键入('nvarchar')、字符_max_LENGTH-1和c.differentitems 0和c.totalCount 0,然后执行('select max(len('+b.TABLE_CATALOG++'.+'+'+b.COLUMN_NAME++'))时的情况
从…起
以上内容基本上只是检查以确保它是一个varchar(max)字段,并且在列中包含一些值。然后,我尝试执行SP并传递需要平均长度的列名和表名,但出现以下错误

Msg 156,第15级,状态1,第57行 关键字“exec”附近的语法不正确

我学到了不能从函数调用动态SQL,也不能从CASE语句调用SP。所以在这一点上,它似乎是一个陷阱22,我不能做什么,我需要使用SQL。有人能想出解决办法吗?或者我在这方面运气不佳?

实际上,可以在标量UDF中执行动态SQL,它只需要是SQLCLR UDF;-)。但使用进程内/内部连接(即
SqlConnection(“Context-connection=true;”;
)实现这一点相当简单。也就是说,可以将程序集设置为安全

此外,对象/列/索引名都是NVARCHAR。和对象(如果不是其他对象)被声明为
sysname
,这是
NVARCHAR(128)
的别名。仅供参考

因此,类似于以下内容(我已经测试过,它确实有效):

[Microsoft.SqlServer.Server.SqlFunction(Name = "GetAvgBytes",
    IsDeterministic = false, IsPrecise = true, DataAccess = DataAccessKind.Read)]
public static SqlInt32 GetAvgBytes([SqlFacet(MaxSize = 128)] SqlString TableName,
    [SqlFacet(MaxSize = 128)] SqlString ColumnName)
{
    int _AvgBytes = -1;
    SqlConnection _Connection = new SqlConnection("Context Connection = true;");
    SqlCommand _Command = _Connection.CreateCommand();
    _Command.CommandType = CommandType.Text;
    _Command.CommandText = "SELECT @AvgBytes = AVG(DATALENGTH(" + ColumnName.Value
                        + ")) FROM " + TableName.Value + " WITH (NOLOCK);";

    SqlParameter _Param = new SqlParameter("@AvgBytes", DbType.Int32);
    _Param.Direction = ParameterDirection.Output;
    _Command.Parameters.Add(_Param);

    try
    {
        _Connection.Open();

        _Command.ExecuteNonQuery();

        _AvgBytes = (int)_Param.Value;
    }
    finally
    {
        _Connection.Close();
    }

    return _AvgBytes;
}