Frage Kann ich eine einmalige Verwendung in einem Skript oder einer gespeicherten Prozedur erstellen?


Gibt es in SQL Server 2005 ein Konzept für eine einmalige oder lokale Funktion, die innerhalb eines SQL-Skripts oder einer gespeicherten Prozedur deklariert wird? Ich möchte etwas Komplexität in einem Skript abstrahieren, das ich schreibe, aber es würde erfordern, eine Funktion deklarieren zu können.

Nur neugierig.


76
2018-06-11 14:30


Ursprung


Antworten:


Du kannst anrufen CREATE Function nahe dem Anfang Ihres Skripts und DROP Function nahe dem Ende.


52
2018-06-11 14:32



Sie können temporäre gespeicherte Prozeduren erstellen wie:

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

in einem SQL-Skript, aber nicht funktioniert. Sie könnten das Ergebnis des Procspeichers jedoch in einer temporären Tabelle speichern und diese Informationen später im Skript verwenden.


63
2018-06-11 14:37



Gemeinsame Tabellenausdrücke Sie können definieren, was im Wesentlichen Ansichten sind, die nur im Rahmen Ihrer Auswahl, Einfügen, Aktualisieren und Löschen von Aussagen dauern. Je nachdem, was Sie tun müssen, können sie sehr nützlich sein.


20
2018-06-11 14:35



Ich weiß, dass ich für das Vorschlagen von dynamischem SQL kritisiert werden könnte, aber manchmal ist es eine gute Lösung. Stellen Sie sicher, dass Sie die Sicherheitsaspekte verstehen, bevor Sie dies in Betracht ziehen.

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'

6
2017-09-23 17:23



In Skripten haben Sie mehr Optionen und einen besseren Einblick in die rationale Zerlegung. Schauen Sie in den SQLCMD-Modus (Abfrage-Menü -> SQLCMD-Modus), insbesondere die Befehle: setvar und: r.

Innerhalb einer gespeicherten Prozedur sind Ihre Möglichkeiten sehr begrenzt. Sie können keine Funktion direkt mit dem Rumpf einer Prozedur definieren. Das Beste, was Sie tun können, ist so etwas mit dynamischem 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

Dies entspricht einer globalen temporären Funktion, wenn so etwas existiert. Es ist immer noch für andere Benutzer sichtbar. Sie können die @@ SPID Ihrer Verbindung anhängen, um den Namen zu individualisieren, aber das würde dann erfordern, dass der Rest der Prozedur auch dynamisches SQL verwendet.


2
2018-06-12 05:29



Das Folgende ist, was ich in der Vergangenheit verwendet habe, um die Notwendigkeit für eine skalare UDF in MS SQL zu erreichen:

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

Dieser Ansatz, der eine globale Variable für das PROCEDURE verwendet, ermöglicht es Ihnen, die Funktion nicht nur in Ihren Skripten, sondern auch in Ihren Dynamic SQL-Anforderungen zu verwenden.


2
2017-08-29 20:49