Выполнение динамического SQL в функции SQLServer 2005 - PullRequest
20 голосов
/ 30 сентября 2008

Я предрежу этот вопрос словами: я не думаю, что он разрешим. У меня также есть обходной путь, я могу создать хранимую процедуру с OUTPUT, чтобы выполнить это, просто проще кодировать разделы, где мне нужна эта контрольная сумма, используя функцию.

Этот код не будет работать из-за вызовов Exec SP_ExecuteSQL @SQL. Кто-нибудь знает, как выполнить динамический SQL в функции? (и еще раз, я не думаю, что это возможно. Если это так, я бы хотел знать, как обойти это!)

Create Function Get_Checksum
(
    @DatabaseName      varchar(100),
    @TableName         varchar(100)
)
RETURNS FLOAT
AS
BEGIN

 Declare @SQL        nvarchar(4000)
 Declare @ColumnName varchar(100)
 Declare @i          int
 Declare @Checksum   float
 Declare @intColumns table (idRecord int identity(1,1), ColumnName varchar(255))
 Declare @CS         table (MyCheckSum bigint)

 Set @SQL = 
        'Insert Into @IntColumns(ColumnName)' + Char(13) + 
        'Select Column_Name' + Char(13) +
        'From   ' + @DatabaseName + '.Information_Schema.Columns (NOLOCK)' + Char(13) +
        'Where  Table_Name = ''' + @TableName + '''' + Char(13) +
        '       and Data_Type = ''int''' 

 -- print @SQL

 exec sp_executeSql @SQL

 Set @SQL = 
        'Insert Into @CS(MyChecksum)' + Char(13) + 
        'Select '

 Set @i = 1

 While Exists(
       Select 1
       From   @IntColumns
       Where  IdRecord = @i)
 begin
       Select @ColumnName = ColumnName
       From   @IntColumns
       Where  IdRecord = @i

       Set @SQL = @SQL + Char(13) + 
            CASE WHEN @i = 1 THEN 
                 '    Sum(Cast(IsNull(' + @ColumnName + ',0) as bigint))'
                 ELSE
                 '    + Sum(Cast(IsNull(' + @ColumnName + ',0) as bigint))'
            END

       Set @i = @i + 1
 end

 Set @SQL = @SQL + Char(13) + 
      'From ' + @DatabaseName + '..' + @TableName + ' (NOLOCK)'

 -- print @SQL

 exec sp_executeSql @SQL

 Set @Checksum = (Select Top 1 MyChecksum From @CS)

 Return isnull(@Checksum,0)

END
GO

Ответы [ 5 ]

15 голосов
/ 30 сентября 2008

Это «обычно» не может быть сделано, так как SQL Server рассматривает функции как детерминированные, что означает, что для данного набора входных данных он всегда должен возвращать одни и те же выходные данные. Хранимая процедура или динамический sql могут быть недетерминированными, поскольку могут изменять внешнее состояние, например таблицу, на которую полагаются.

Учитывая, что в SQL-сервере функции всегда детерминированы, было бы плохой идеей с точки зрения будущего обслуживания пытаться обойти это, поскольку это может вызвать довольно большую путаницу для любого, кто должен будет поддерживать код в будущем.

5 голосов
/ 15 сентября 2012

Вот решение

Решение 1: Вернуть динамическую строку из функции затем

Declare @SQLStr varchar(max) 
DECLARE @tmptable table (<columns>)
set @SQLStr=dbo.function(<parameters>)
insert into @tmptable
Exec (@SQLStr)

select * from @tmptable

Решение 2: вызывать вложенные функции путем передачи параметров.

2 голосов
/ 30 сентября 2008

Вы можете обойти это, вызвав расширенную хранимую процедуру, со всеми сопутствующими хлопотами и проблемами безопасности.

http://decipherinfosys.wordpress.com/2008/07/16/udf-limitations-in-sql-server/

http://decipherinfosys.wordpress.com/2007/02/27/using-getdate-in-a-udf/

0 голосов
/ 30 сентября 2008

Спасибо всем за ответы.

Рон: К вашему сведению, использование этого сообщения приведет к ошибке.

Я согласен, что не делать то, что я изначально задумал, является лучшим решением, я решил пойти другим путем. Два моих выбора заключались в использовании sum(cast(BINARY_CHECKSUM(*) as float)) или выходного параметра в хранимой процедуре. После модульного тестирования скорости каждого я решил использовать sum(cast(BINARY_CHECKSUM(*) as float)), чтобы получить сопоставимое значение контрольной суммы для данных каждой таблицы.

0 голосов
/ 30 сентября 2008

Поскольку функции должны хорошо работать с оптимизатором запросов, их довольно много. Эта ссылка относится к статье, в которой подробно рассматриваются ограничения UDF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...