source

스크립트 또는 스토어드 프로시저에서 일회용 기능을 만들 수 있습니까?

lovecheck 2023. 4. 7. 21:34
반응형

스크립트 또는 스토어드 프로시저에서 일회용 기능을 만들 수 있습니까?

SQL Server 2005에서는 SQL 스크립트 또는 Stored Procedure 내에서 일회성 또는 로컬 함수의 개념이 선언되어 있습니까?쓰고 있는 스크립트의 복잡함을 추상화하고 싶은데 함수를 선언할 수 있어야 합니다.

그냥 궁금해서.

다음과 같은 온도 저장 프로시저를 만들 수 있습니다.

create procedure #mytemp as
begin
   select getdate() into #mytemptable;
end

SQL 스크립트에 포함되지만 기능하지는 않습니다.proc에게 결과를 temp table에 저장하도록 할 수 있습니다.그 후 스크립트에서 이 정보를 사용합니다.

전화하시면 됩니다.CREATE Function스크립트의 선두에 가까워지고 있습니다.DROP Function거의 끝나갈 무렵에.

[ Common Table Expressions ]를 사용하면 기본적으로 선택, 삽입, 갱신 및 삭제 스테이트먼트의 범위 내에서만 지속되는 뷰를 정의할 수 있습니다.무엇을 해야 하는지에 따라 매우 유용할 수 있습니다.

동적 SQL을 제안하는 것으로 인해 비판을 받을 수도 있지만, 때로는 이것이 좋은 솔루션일 수도 있습니다.이 문제를 검토하기 전에 보안에 대한 영향을 이해해야 합니다.

DECLARE @add_a_b_func nvarchar(4000) = N'SELECT @c = @a + @b;';
DECLARE @add_a_b_parm nvarchar(500) = N'@a int, @b int, @c int OUTPUT';

DECLARE @result int;
EXEC sp_executesql @add_a_b_func, @add_a_b_parm, 2, 3, @c = @result OUTPUT;
PRINT CONVERT(varchar, @result); -- prints '5'

다음은 MS SQL에서 스칼라 UDF의 필요성을 충족시키기 위해 사용한 것입니다.

IF OBJECT_ID('tempdb..##fn_Divide') IS NOT NULL DROP PROCEDURE ##fn_Divide
GO
CREATE PROCEDURE ##fn_Divide (@Numerator Real, @Denominator Real) AS
BEGIN
    SELECT Division =
        CASE WHEN @Denominator != 0 AND @Denominator is NOT NULL AND  @Numerator != 0 AND @Numerator is NOT NULL THEN
        @Numerator / @Denominator
        ELSE
            0
        END
    RETURN
END
GO

Exec ##fn_Divide 6,4

PROCEDURE에 글로벌 변수를 사용하는 이 접근방식을 사용하면 스크립트뿐만 아니라 다이내믹 SQL 요구에도 함수를 사용할 수 있습니다.

스크립트에는 보다 많은 옵션이 있으며 합리적인 분해가 가능합니다.SQLCMD 모드(SSMS -> Query Menu -> SQLCMD 모드), 특히 :setvar 및 :r 명령어를 조사합니다.

저장 프로시저에서는 옵션이 매우 제한됩니다.프로시저 본문을 사용하여 함수를 직접 정의할 수 없습니다.다이내믹 SQL에서는 다음과 같은 작업을 수행할 수 있습니다.

create proc DoStuff
as begin

  declare @sql nvarchar(max)

  /*
  define function here, within a string
  note the underscore prefix, a good convention for user-defined temporary objects
  */
  set @sql = '
    create function dbo._object_name_twopart (@object_id int)
    returns nvarchar(517) as
    begin
      return 
        quotename(object_schema_name(@object_id))+N''.''+
        quotename(object_name(@object_id))
    end
  '

  /*
  create the function by executing the string, with a conditional object drop upfront
  */
  if object_id('dbo._object_name_twopart') is not null drop function _object_name_twopart
  exec (@sql)

  /*
  use the function in a query
  */
  select object_id, dbo._object_name_twopart(object_id) 
  from sys.objects
  where type = 'U'

  /*
  clean up
  */
  drop function _object_name_twopart

end
go

이는 글로벌 임시 함수에 가깝습니다(이러한 함수가 존재하는 경우).다른 사용자가 볼 수 있습니다.연결의 @@SPID를 추가하여 이름을 고유하게 만들 수 있지만, 나머지 절차에서도 동적 SQL을 사용해야 합니다.

지금 이걸 찾는 사람을 위한 또 다른 아이디어야.tempdb에는 항상 영속적인 함수를 작성할 수 있습니다.이 함수는 일시적인 객체임을 나타내기 위해 ## 또는 # 앞에 붙지 않습니다.서버가 삭제되거나 서버가 재시작되고 tempdb가 다시 작성될 때까지 "영구적으로" 유지됩니다.중요한 것은, 자신의 가비지 수집에 실패했을 경우, 서버가 재기동하면, 최종적으로 없어지는 것입니다.

함수의 범위는 TempDB 내이지만 3개의 부품 이름을 가진 서버상의 다른 데이터베이스를 참조할 수 있습니다.(dbname).schema.objectname) 또는 그 이상의 기능을 수행하는 데 필요한 모든 파라미터를 전달할 수 있기 때문에 다른 데이터베이스 내의 다른 오브젝트를 볼 필요가 없습니다.

언급URL : https://stackoverflow.com/questions/981451/can-i-create-a-one-time-use-function-in-a-script-or-stored-procedure

반응형