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.
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
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.
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 .