web-dev-qa-db-fra.com

comment tester si XML = '' dans le serveur SQL?

Je travaille avec SQL Server 2005 et j'ai eu une situation où de nombreuses valeurs peuvent être passées dans un paramètre.

Sur cette base: passage de plusieurs valeurs pour un paramètre SQL cette procédure utilise XML comme paramètre.

voici le code de la procédure stockée:

CREATE PROCEDURE [DENORMV2].[udpProductBulletPointSelectByTier1NoteTypeCode] (  
    @Tier1 VARCHAR(10),  
    @LanguageID INT,  
    @SeasonItemID VARCHAR(5) = NULL,
    @ListNoteTypeCode XML,  
    @CacheDuration INT OUTPUT )  
    WITH EXECUTE AS 'webUserWithRW'  
AS

        SELECT  pbp.Tier1, pbp.LanguageId, pbp.NoteText, pbp.NoteTypeCode,  
                pbp.NoteGroup, pbp.SortOrder  
        FROM    dbo.ProductBulletPoint pbp  

        WHERE   Tier1 = @Tier1 
          AND   LanguageId = @LanguageID 
          AND   (      SeasonItemId = @SeasonItemID  
                  OR
                       @SeasonItemID is null
                )

          AND pbp.NoteTypeCode IN (

                 SELECT  NoteTypeCode=BulletPoint.NoteTypeCode.value('./text()[1]', 'varchar(50)')
                   FROM  @ListNoteTypeCode.nodes('/BulletPoint/NoteTypeCode') AS BulletPoint ( NoteTypeCode )

          )

SELECT  @CacheDuration = Duration  
FROM    dbo.CacheDuration  
WHERE   [Key] = 'Product'
GO

plus d'informations sur cette procédure ici

voici un exemple de la façon dont on peut l'appeler:

declare @p5 int  set @p5=86400 
exec DenormV2.udpProductBulletPointSelectByTier1NoteTypeCode
@Tier1=N'WW099',
@LanguageID=3,
@SeasonItemID=N'16AUT',
@ListNoteTypeCode=N'<BulletPoint><NoteTypeCode>GarmentComposition</NoteTypeCode><NoteTypeCode>FootwearAccessoryComposition</NoteTypeCode></BulletPoint>',
@CacheDuration=@p5 output  select @p5

Question:

quelle est la meilleure façon de savoir si le paramètre @ListNoteTypeCode XML est vide?

et s'ils appellent cette procédure comme ceci:

declare @p5 int  set @p5=86400 
exec DenormV2.udpProductBulletPointSelectByTier1NoteTypeCode
@Tier1=N'WW099',
@LanguageID=3,
@SeasonItemID=N'16AUT',
@ListNoteTypeCode=N'',
@CacheDuration=@p5 output  select @p5

comme il a été suggéré ici Je pourrais éviter complètement la sélection en testant le paramètre @ListNoteTypeCode.

Mon objectif principal dans ce scénario est de récupérer les données dans les meilleures performances possibles, car cette procédure n'est pas mise en cache dans les serveurs Web et est appelée plus d'un million de fois par jour.

7
Marcello Miorelli

Vous pouvez vérifier l'absence de NULL et de nœuds (méthode exist de type xml):

@ListNoteTypeCode is NULL OR @ListNoteTypeCode.exist('*') = 0

Votre XPath peut être plus spécifique, si nécessaire:

@ListNoteTypeCode is NULL OR @ListNoteTypeCode.exist('/BulletPoint/NoteTypeCode/text()') = 0
7
i-one

Une autre façon de tester un paramètre, une variable ou une colonne XML vide est de vérifier le DATALENGTH. Tout élément XML vide doit faire 5 octets. Par exemple:

DECLARE @Test TABLE (XmlParam XML NULL);
INSERT INTO @Test ([XmlParam]) VALUES (NULL), (N''), (N'g');

SELECT t.[XmlParam],
       DATALENGTH(t.[XmlParam]) AS [DATALENGTH],
       CASE (ISNULL(DATALENGTH(t.[XmlParam]), 5))
          WHEN 5 THEN 'EMPTY'
          ELSE 'Not Empty'
       END AS [IsEmpty]
FROM   @Test t;

Retour:

XmlParam     DATALENGTH    IsEmpty
--------     ----------    ---------
NULL         NULL          EMPTY
             5             EMPTY
g            9             Not Empty

Veuillez noter que j'ai utilisé ISNULL(DATALENGTH(t.[XmlParam]), 5) car cela devrait convenir pour vérifier un paramètre ou une variable. Si vous vérifiez une colonne, il peut être préférable d'utiliser XmlColumn IS NULL OR DATALENGTH(XmlColumn) = 5.

Veuillez également noter que bien qu'il soit possible pour la représentation interne des données XML de changer entre les versions, j'ai testé sur SQL Server 2008 R2, 2012 et 2014 et la taille d'un élément XML vide est toujours 5.

3
Solomon Rutzky

Mon XML utilise le schéma.
DATALENGTH ne fonctionnera certainement pas .
Même sans données, le schéma occupera toujours des espaces aléatoires.

Cela testera les éléments/nœuds manquants (fonctionne avec ou sans schéma):

SELECT ISNULL(@ListNoteTypeCode.exist('*:BulletPoint/*:NoteTypeCode'), 0)[HasRows]

Avec cela à l'écart, le but de votre question était d'améliorer les performances.
Vous utilisez une sous-requête corrélée! : O
Ouais! Déplacez-le dans une table-variable avec un PK sur NoteTypeCode.
Ensuite, joignez-vous à votre variable de table et oubliez tout cela Test-For-Missing-Xml .

0
MikeTeeVee