2010-12-27 8 views
4

Ich habe eine benutzerdefinierte Funktion in SQL Server (in .NET geschrieben), die Text bereinigt. Ich frage mich, wie man mit Null-Eingaben umgehen kann. HierSQL Server - Umgang mit Null-Eingabe in benutzerdefinierten CLR-Funktion (UDF) mit OnNullCall

ist die Funktion in C#:

[Microsoft.SqlServer.Server.SqlFunction] 
public static SqlChars cleanEstActText(SqlChars input) 
{ 
    SqlChars cascadingSqlChar = removeNBSP(input); 
    cascadingSqlChar = optimizeFontTags(cascadingSqlChar); 

    return cascadingSqlChar; 
} 

Dies ist der Fehler in SQL, wenn die Funktion jede Null-Daten bekommt:

A .NET Framework error occurred during execution of user-defined routine or aggregate "removeNBSP": 
System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values. 
System.Data.SqlTypes.SqlNullValueException: 
    at System.Data.SqlTypes.SqlChars.get_Value() 
    at UserDefinedFunctions.removeNBSP(SqlChars input) 

Lesen auf SO und Google führte mich zum OnNullCall Attribut Das sieht vielversprechend aus.

Von MSDN:

true, wenn die Methode aufgerufen wird, wenn null (Nothing in Visual Basic) Eingabeargumente in dem Methodenaufruf angegeben werden; false, wenn die Methode einen NULL-Wert (Nothing in Visual Basic) zurückgibt, wenn einer ihrer Eingabeparameter null ist (Nothing in Visual Basic).

Klingt genau wie, was ich will; Wenn ich null bekomme, pass einfach null durch. Ich bin mir nicht ganz sicher, wie ich es implementieren soll, also überprüfe ich MSDN erneut (http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqlmethodattribute.aspx), und überschreibe die erste Zeile von meine Funktion von

[Microsoft.SqlServer.Server.SqlFunction] 

zu

[Microsoft.SqlServer.Server.SqlMethod(OnNullCall = false, IsMutator = false, InvokeIfReceiverIsNull = false)] 

Wenn ich das tue, ich erhalte eine Fehlermeldung in SQL jedes Mal, wenn ich es verwenden:

Cannot find either column "dbo" or the user-defined function or aggregate "dbo.cleanEstActText", or the name is ambiguous. 

Bin ich falsch Umsetzung OnNullCall? Sollte ich etwas anderes machen? Gibt es wirklich einen guten Weg, um meine Funktion durch Null gehen zu lassen?

Antwort

7

können Sie dies versuchen, eine IsNull Propery

[Microsoft.SqlServer.Server.SqlFunction] 
public static SqlChars cleanEstActText(SqlChars input) 
{ 

    if (input.IsNull) return null; 

    SqlChars cascadingSqlChar = removeNBSP(input); 
    cascadingSqlChar = optimizeFontTags(cascadingSqlChar); 

    return cascadingSqlChar; 
} 

Alle Nullable sqldata Typen haben.

Dank Hari

+0

Bei den beiden oben genannten Lösungen handelt es sich lediglich um Problemumgehungen, die das Problem nicht beheben. Haris Antwort ist die richtige. – alphadogg

+0

@alphadogg und Hari, das ist tatsächlich _not_ die richtige Antwort. Zumindest nicht im Zusammenhang mit der Frage. Es ist nur die richtige Antwort, wenn mehrere Eingabeparameter vorhanden sind und mindestens einer von ihnen einen NULL-Wert gültig übergeben kann. Andernfalls sollten Sie 'WITH RETURNS NULL ON NULL INPUT' in der' CREATE FUNCTION' verwenden, wie in meiner Antwort beschrieben. –

0

Bearbeiten: Dies wurde vor der jetzt angenommenen Antwort oben geschrieben. Sehen Sie das stattdessen.

Ich bin immer noch überzeugt, dass es einen Weg gibt, dies zu tun, aber ich habe es nicht gefunden (ich weiß nicht genug darüber, wie SQL mit der CLR ohnehin interagiert).

Um die Problemumgehung zu umgehen, habe ich die ziemlich offensichtliche Sache getan: auf Nullen prüfen.

Select dbo.cleanEstActText(EstActText1) 
From BLEstActivity 
Where EstActText1 is not NULL 
1

@Josh, für das, was es wert ist, rufe ich meine CLR-Funktionen auf, indem ich alle Parameter mit einer Koaleszenzfunktion umschließe. So etwas wie select myFunc(coalesce(fld1,'')). Dann überprüfe ich in meiner CLR-Funktion die Werte der Parameter ganz oben, etwa . Natürlich können Sie tun, was immer Sie in der Funktion brauchen, aber das ist das allgemeine Muster, das ich verwendet habe, um das Null-Problem mit CLR-Procs/Funktionen zu umgehen. Es ist eine Hektik, sich daran zu erinnern, sie jedes Mal zu verpacken, wenn ich sie benutze, aber es funktioniert.

+0

Das ziemlich nützlich zu sein scheint. Das einzige Problem ist, dass Null und '' möglicherweise differenziert werden müssen. Ich denke jedoch, dass in meinem Fall das Ändern der leeren Saiten auf Null genauso gut funktionieren würde. Vielen Dank. – jtpereyda

+2

@EvilDr Dies ist eigentlich ein schlechtes, verschlungenes und unnötiges Muster. Wenn Sie für mindestens einen Eingabeparameter NULL-Werte in Ihren Code eingeben müssen, können Sie einfach alle/alle Eingabeparameter mit der Eigenschaft "IsNull" testen, die alle SqlTypes haben. Wenn KEINE der Eingabeparameter NULL übergeben, können Sie den Methodenaufruf an erster Stelle überspringen, indem Sie 'WITH RETURNS NULL ON NULL INPUT 'angeben. Bitte lesen Sie meine [antworten] (http://stackoverflow.com/a/28728440/577765) für Details. –

+1

Eigentlich ja ich stimme zu. Nach mehr Lektüre und Betrachtung war die Antwort in Bezug auf 'IF value.IsNull' kombiniert mit' If String.IsNullOrWhitespace' perfekt. Ihre Gesamteingaben zu jedem Punkt hier sind hervorragend. – EvilDr

3

Die akzeptierte Antwort ist nicht richtig, obwohl es technisch funktioniert. Das Problem beim Suchen nach NULL im Code selbst ist, dass der Code aufgerufen wird und diese Prüfung durchführen muss. Dies ist nur erforderlich, wenn Sie zulassen möchten, dass ein oder mehrere Parameter einen gültigen NULL-Wert übergeben, ohne dass die Ausführung der Methode übersprungen wird.

Dies ist definitiv möglich, aber leider nicht durch den Visual Studio/SSDT-Publishing-Mechanismus, der das gesamte T-SQL für Sie erstellt. Um dies zu erreichen, müssen Sie entweder:

  • manuell bereitstellen, die T-SQL CREATE FUNCTION Anweisung
  • ein ALTER FUNCTION Sie nach dem Code auf SQL Server veröffentlicht

In jedem Fall Die Syntax dafür lautet wie auf der MSDN-Seite für CREATE FUNCTION beschrieben: WITH RETURNS NULL ON NULL INPUT.

Um es in vollem Kontext zu setzen:

CREATE FUNCTION SchemaName.FunctionName ({ parameter_list }) 
RETURNS DataType 
WITH RETURNS NULL ON NULL INPUT 
AS EXTERNAL NAME ... 

Auch die im Auge behalten, wenn diese Option angegeben wird, dann jeder Eingangsparameter, die NULL ist bewirkt, dass die Funktion übersprungen und NULL zurückkehren werden.

UPDATE:
Bitte stimmen Sie über die folgende Microsoft Connect-Vorschlag, so dass hoffentlich Unterstützung für die OnNullCall Eigenschaft des SqlFunction Attribut hinzugefügt wird:

Implement OnNullCall property in SqlFunctionAttribute for RETURNS NULL ON NULL INPUT