2015-10-07 1 views
0

Je dois créer une fonction définie par l'utilisateur qui fonctionnerait de manière similaire à la fonction du système ISNULL dans le respect qu'il accepterait des arguments de tout type et renverrait la même valeur type. Comment cela est-il fait? L'utilisation de SQL_VARIANT en tant que type de données ne fonctionnerait pas car les valeurs SQL_VARIANT nécessitent un transtypage explicite. ISNULL effectue implicitement les conversions de type de données. Comment déclarer les types génériques qui ne nécessitent pas de conversion explicite?Fonction définie par l'utilisateur SQL Server prenant des arguments de tout type comme ISNULL

Laissez-moi le préciser. Je ne cherche pas à reproduire la fonctionnalité de la fonction ISNULL. J'ai utilisé la fonction ISNULL comme un modèle d'une fonction qui prend deux arguments de n'importe quel type de données pris en charge par SQL Server et renvoie la valeur du même type de données que les arguments.

D'autres fonctions SQL Server implémentent le même modèle: acceptent les arguments dont le type de données n'est pas explicitement déclaré et renvoient la valeur d'un autre type de données non explicitement déclaré lors de la définition de la fonction. Les exemples sont: NULLIF, CAST, CONVERT.

Je me demande comment ce modèle peut être accompli, car toute fonction UDF requiert une définition explicite des arguments et des types de données de valeur de retour.

+1

Quelle devrait être la valeur de remplacement pour chaque type? Remplacer une chaîne NULL avec une chaîne vide est plutôt évident, mais quelle est la non-valeur pour datetime? Est-ce que Zéro est vraiment la non-valeur d'un type numérique? Que veux-tu accomplir? – Shnugo

+1

T-SQL n'a pas de génériques et les types de retour de fonction définis par l'utilisateur sont statiques (et obligatoires), ce que vous demandez littéralement est impossible. Il y a plusieurs choses que je peux penser qui pourraient trier-de réaliser ce que vous voulez (comme une procédure stockée qui donne une table, ou SQL dynamique) mais aussi de bonnes raisons pour lesquelles vous ne voudriez pas les utiliser dans le code de production. Puisque 'ISNULL' existe déjà et fonctionne très bien, qu'est-ce que vous voulez exactement c'est" similaire "à' ISNULL', et pour quoi faire? –

+0

Shnugo, le point est d'avoir une fonction agnostique du type d'argument et est capable d'en prendre, comme le font les fonctions comme ISNULL ou NULLIF. Il ne s'agit pas d'implémenter une autre version de ISNULL, mais de pouvoir créer une nouvelle fonction, capable de gérer les arguments de n'importe quel moment, et ce qui est plus important, renvoyer la valeur du même type que les arguments. – Ramzay

Répondre

0

Je viens de répondre une question qui est liée en quelque sorte: https://stackoverflow.com/a/32985478/5089204

Il n'y a pas moyen sûr de traiter avec des valeurs vides. ISNULL est très bon dans la plupart des cas, mais ne compilera pas si vous n'avez pas les deux paramètres d'un type implicitement convertible.

Regardez comment cela est traité en XML. Collez-le simplement dans une fenêtre de requête vide et exécutez:

--The NULL-element is not there at all 
SELECT 'text' AS filled 
     ,'' AS empty 
     ,NULL AS NotThere 
FOR XML PATH('row'); 

--The NULL-element is rendered using "nil" 
SELECT 'text' AS filled 
     ,'' AS empty 
     ,NULL AS NotThere 
FOR XML PATH('row'),ELEMENTS XSINIL  

--Look at this: Both columns are called "TheName". They are implicitly concatenated 
SELECT 'a' AS TheName 
     ,'b' AS TheName 
FOR XML PATH('row') 

--That leads to: Concatenate nothing with an empty string will at least return the empty string. 
--this is other/better than ISNULL, because it will work with any type... 
SELECT NULL AS TheName 
     ,'' AS TheName 
FOR XML PATH('row') 

--now an example with table data 
DECLARE @tbl TABLE(int1 INT, int2 INT); 
INSERT INTO @tbl VALUES(NULL,1); --first value is null 

--int1 is swallowed 
SELECT * 
FROM @tbl 
FOR XML PATH('row') 

--both elements are there 
SELECT int1, '' AS int1 --ISNULL(int1,'') would not compile here... 
     ,int2, '' AS int2 
FROM @tbl 
FOR XML PATH('row') 

--This is the result of the last example: Look what happens to the empty int element, its Zero! 
--This is the way this is handled in XML conversions. Try it with other types (like 'date' [result is 1900-01-01] or any other type)... 
DECLARE @a XML='<row><int1></int1><int2>1</int2></row>'; 
SELECT a.b.value('int1[1]','int') AS int1 
     ,a.b.value('int2[1]','int') AS int2 
FROM @a.nodes('/row') a(b) 
+0

C'est vraiment fascinant et très instructif. Je vous remercie de partager cette information. Je suis sûr que je trouverais un bon usage pour cela. Cependant, cela ne m'apporte pas plus près de la réponse à ma question: comment SQL Server implémente des fonctions comme ISNULL, CONVERT, CAST, NULLIF sans paramètres et les types de données de valeurs de retour sont explicitement définis? – Ramzay