Wie deklariere ich eine Funktion als deterministisch im SQL Server?



  • Hallo,

    nach unendlichlanger Suche komme ich einfach zu keinem Ergebnis. Ich will eine indizierte View im SQL Server erstellen, diese verwendet allerdings eine benutzerdefinierte Funktion. Jedoch um ein Index auf die View zu erstellen, muss meine verwendete Funktion deterministisch sein. Bei der Abfrage auf IsDeterministic ergab dies, dass sie es nicht ist. Jetzt gibt es wohl ein Attribut, dass ich einfach setzen kann, um eine Funktion als deterministisch zu kennzeichen.

    Weiss jemand, wie man eine Funktion auf deterministisch deklariert?

    Wäre für jede Antwort dankbar.

    Gruss,
    chullain



  • Gar nicht, du must deine Function so aufbauen das diese Deterministisch ist. Deterministisch bedeutet, dass eine Funktion immer den selben Wert zurückliefert (auch interne Funktionen), somit ist eine Funktion wie GetDate() nicht deterministisch, das diese beim Aufruf immer einen anderen Wert zurückliefert.
    Suche mal in der MSDN, für den SQL Server, nach "nicht deterministische Funktionen".

    Gruß





  • Wenn die user-defined-function in .NET implementiert ist muss man schon selbst angeben ob sie deterministisch ist oder nicht:

    http://msdn.microsoft.com/de-de/library/ms131050(SQL.90).aspx

    Für T-SQL Funktionen ermittelt der SQL Server das selbst - wie schon geschrieben wurde.



  • Danke auf jeden Fall schon mal für Euere Antworten, auch wenn sie jetzt enttäuschend für mich sind. 😞

    D.h. im Grunde genommen, wenn die Funktion ein Select auf eine Tabelle macht und diesen Select auch zurückgibt, das die Funktion von vorne herein als nicht deterministisch markiert wird.

    Gruss,
    chullain



  • So Sieht meine Funktion aus. Kann man diese Funktion irgendwie gestalten, dass sie deterministisch wird? Bzw. gibt es ein Link, wo ich nachlesen kann, welche Kriterien bei wichtig sind, dass der SQL Server, die Funktion als deterministisch anerkennt?

    CREATE FUNCTION udfGetZINObjectTreeEx_4 (@ZINTag VARCHAR(50), @Zyklus VARCHAR(50))
    RETURNS @Sagentobjekte TABLE
    (
      SagentObjektID INT,
      SagentParentObjektID INT NULL,
      SagentObjektName VARCHAR(50),
      ZINTag VARCHAR(50),
      TreeLevel INT,
      Zyklus VARCHAR(50),
      SagentObjektCounterID INT,
      Lineage VARCHAR (2000)
    ) WITH SCHEMABINDING
    AS
    BEGIN
      DECLARE @TreeLevel INT;
      DECLARE @ZINObjectID INT;
    
      SET @ZINObjectID = (SELECT SagentobjektID FROM dbo.SagentObjekte WHERE ZINTag = @ZINTag AND SagentObjektZyklus = @Zyklus);
      --
      SELECT @TreeLevel = 0;
      --
      -- Wurzelknoten ermitteln und in #NOSObject schreiben
      --
      INSERT INTO @Sagentobjekte
      SELECT SagentObjektID        = A.SagentObjektID,
             SagentParentObjektID  = A.ZINChildID,
             SagentObjektName      = A.SagentObjektName,
             ZINTag                = A.ZINTag,
             TreeLevel             = @TreeLevel,
             Zyklus                = @Zyklus,
             SagentObjektCounterID = A.SagentObjectCounterID,
             Lineage               = RIGHT ('00000000' + CAST (@ZINObjectID AS VARCHAR(8)), 8)
      FROM dbo.SagentObjekte A
      WHERE SagentObjektID = @ZINObjectID
      AND
            A.SagentObjektZyklus = @Zyklus;
    
      --
      -- Unterknoten hinzufügen, bis keine mehr zu vergeben sind
      --
      WHILE @@ROWCOUNT > 0
      BEGIN
        SELECT @TreeLevel = @TreeLevel + 1;
        INSERT INTO @Sagentobjekte
        SELECT SagentObjektID        = A.SagentObjektID,
               SagentParentObjektID  = A.ZINChildID,
               SagentObjektName      = A.SagentObjektName,
               ZINTag                = A.ZINTag,
               TreeLevel             = @TreeLevel,
               Zyklus                = @Zyklus,
               SagentObjektCounterID = A.SagentObjectCounterID,
               Linage                = TMP.Lineage + RIGHT ('00000000' + CAST (A.SagentObjektID AS VARCHAR(8)), 8)
        FROM dbo.SagentObjekte A INNER JOIN @Sagentobjekte TMP
                                ON A.ZINChildID = TMP.SagentObjektID
        WHERE 
          A.SagentObjektZyklus = @Zyklus
        AND EXISTS
        (
          SELECT SagentObjektID, SagentParentObjektID, SagentObjektName, ZINTag, TreeLevel, Zyklus, SagentObjektCounterID, Lineage
          FROM @Sagentobjekte
          WHERE SagentObjektID = A.ZINChildID
        )
        AND NOT EXISTS
        (
          SELECT SagentObjektID, SagentParentObjektID, SagentObjektName, ZINTag, TreeLevel, Zyklus, SagentObjektCounterID, Lineage
          FROM @Sagentobjekte
          WHERE SagentObjektID = A.SagentObjektID
        )
      END
    
      --
      -- Rückgabe an Aufrufer
      --
      RETURN;
    
    END
    

    Gruss,
    chullain



  • Kann ich nicht irgendwie mit der CLR-Routine SQLFunction das Attribut Isdeterministic auf True setzen?



  • Anscheinend kann ich auch keinen grupperiten Index auf Sichten legen, die einen Left outer Join in der Tabelle haben. Is das richtig so?

    Gruss,
    chullain



  • Bitte, das kannst du alles in der MSDN nachlesen. Beim Thema "indexed views" steht das alles beschreiben 🙄



  • Du kannst doch überprüfen ob deine Funktion deterministisch ist.
    Wenn du die gleichen Eingabeparameter verwendest dann sollte die Funktion auch immer das gleiche zurückgeben.
    Macht sie es nicht dann kannst du sie auch nicht als deterministische Funktion verwenden.



  • Funktionen die irgendwie mit Daten aus Tabellen arbeiten wird SQL-Server nie als deterministisch durchgehen lassen. Die Daten in den Tabellen könnten sich ja ändern, und damit könnte sich das Ergebnis der Funktion ändern.


Anmelden zum Antworten