SQLServer 2005 함수에서 동적 SQL 실행
-
02-07-2019 - |
문제
나는이 질문을 말로 표면으로 말할 것입니다. 나는 그것이 해결 될 수 없다고 생각합니다. 또한 해결 방법이 있습니다.이를 수행하기 위해 출력으로 저장된 절차를 만들 수 있습니다. 함수를 사용 하여이 체크섬이 필요한 섹션을 코딩하는 것이 더 쉽습니다.
이 코드는이 코드가 작동하지 않습니다 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
해결책
SQL Server가 기능을 결정 론으로 취급함에 따라 "일반적으로"수행 할 수 없습니다. 즉, 주어진 입력 세트의 경우 항상 동일한 출력을 반환해야합니다. 저장된 절차 또는 동적 SQL은 의존하는 테이블과 같은 외부 상태를 변경할 수 있기 때문에 결정적이지 않을 수 있습니다.
SQL 서버 기능이 항상 결정적이라는 점을 감안할 때, 향후 코드를 지원 해야하는 사람에게 상당히 큰 혼란을 야기 할 수 있기 때문에 미래의 유지 보수 관점에서이를 우회하는 것은 나쁜 생각이 될 것입니다.
다른 팁
다음은 해결책입니다
Solution 1:그런 다음 기능에서 동적 문자열을 반환하십시오
Declare @SQLStr varchar(max)
DECLARE @tmptable table (<columns>)
set @SQLStr=dbo.function(<parameters>)
insert into @tmptable
Exec (@SQLStr)
select * from @tmptable
Solution 2:매개 변수를 전달하여 중첩 기능을 호출하십시오.
모든 승무원 번거 로움과 보안 문제로 확장 저장된 절차를 호출하여이 문제를 해결할 수 있습니다.
http://deciperinfosys.wordpress.com/2008/07/16/udf-limitations-in-sql-server/
http://deciperinfosys.wordpress.com/2007/02/27/using-getdate-in-a-udf/
기능은 쿼리 최적화기와 잘 작동해야하기 때문에 몇 가지 제한이 있습니다. 이 링크 UDF의 깊이의 한계를 논의하는 기사를 나타냅니다.
답장에 감사드립니다.
Ron : FYI, 사용하면 오류가 발생합니다.
나는 원래 의도 한 것을하지 않는 것이 최선의 해결책이라는 데 동의합니다. 나는 다른 길을 가기로 결정했습니다. 나의 두 가지 선택은 사용하는 것이었다 sum(cast(BINARY_CHECKSUM(*) as float))
또는 저장 프로 시저의 출력 매개 변수. 각각의 단위 테스트 속도 후, 나는 함께 가기로 결정했다. sum(cast(BINARY_CHECKSUM(*) as float))
각 테이블의 데이터에 대해 비슷한 체크섬 값을 얻으려면.