Signification de «SET» dans le message d'erreur «La valeur nulle est éliminée par un agrégat ou une autre opération SET»

18

J'ai vu le message «Avertissement ANSI» ci-dessus aujourd'hui lors de l'exécution du script d'un collègue (et je ne sais pas laquelle des nombreuses instructions a provoqué l'affichage de l'avertissement).

Dans le passé, je l'ai ignoré: j'évite moi-même les valeurs nulles et donc tout ce qui pourrait les éliminer est une bonne chose dans mon livre! Cependant, aujourd'hui, le mot «SET» m'a littéralement crié dessus et j'ai réalisé que je ne sais pas quel est le sens du mot est censé être dans ce contexte.

Ma première pensée, basée sur le fait qu'il est en majuscules, est qu'il se réfère au SETmot - clé et signifie «affectation», comme dans

UPDATE <table> SET ...

...ON DELETE SET NULL...

SET IDENTITY_INSERT <table> ON

Selon l'aide de SQL Server, la fonctionnalité «ANSI warnings» est basée sur ISO / ANSI SQL-92, dont la spécification n'utilise qu'une seule fois le terme «Set operation» dans un titre de sous-section, donc dans le cas du titre, dans le section d'attribution des données. Cependant, après une recherche rapide sur Google du message d'erreur, je vois des exemples qui sont des SELECTrequêtes avec apparemment aucune affectation impliquée.

Ma deuxième pensée, basée sur le libellé de l'avertissement SQL Server, était que la signification mathématique de set était implicite. Cependant, je ne pense pas que l'agrégation en SQL soit à proprement parler une opération d'ensemble. Même si l'équipe SQL Server considère qu'il s'agit d'une opération set, quel est le but de mettre le mot «set» en majuscules?

Pendant la recherche sur Google, j'ai remarqué un message d'erreur SQL Server:

Table 'T' does not have the identity property. Cannot perform SET operation.

Les mêmes mots «opération SET» dans le même cas ici ne peuvent faire référence qu'à l'attribution de la IDENTITY_INSERTpropriété, ce qui me ramène à ma première pensée.

Quelqu'un peut-il faire la lumière sur la question?

un jour
la source
J'ai toujours supposé que cela signifiait une opération sur un ensemble de lignes.
Martin Smith
@MartinSmith Je ne pense pas, car il SETest toujours en majuscules comme un mot
JNK
@JNK - Oui, en y réfléchissant, je suppose qu'il doit y avoir une autre opération non agrégée qui déclenche cet avertissement, donc je suppose que si nous découvrons ce que c'est, cela pourrait l'expliquer!
Martin Smith
SELECT * FROM sys.messages WHERE text LIKE '%SET operation%'donne 3 autres résultats qui semblent tous indiquer également un SETmot - clé.
Martin Smith
J'ai fait un peu plus de recherche et cela peut en fait faire référence à des opérations d'ensemble comme dans des ensembles mathématiques. J'ai trouvé beaucoup de références dans les documents SS 2k pour faire set operationsréférence à UNIONet INTERSECTet EXCEPT, mais je ne parviens pas à trouver l'erreur NULLdans aucune de ces circonstances. Je pense que cela peut être un message d'erreur hérité.
JNK

Réponses:

13

Je regardais juste à travers la spécification SQL-92 et j'ai vu un passage qui m'a rappelé cette question.

Il y a en fait un avertissement prescrit pour cette situation comme indiqué ci-dessous

b) Sinon, soit TX la table à une seule colonne qui résulte de l'application de <value expression>à chaque ligne de T et de l'élimination des valeurs nulles. Si une ou plusieurs valeurs nulles sont éliminées, alors une condition d'achèvement est levée: avertissement - valeur nulle éliminée dans la fonction set .

Je suppose que le SETdans le message d'erreur SQL Server est une référence à la fonction set de ce message d'erreur bien que je ne sais pas pourquoi cela ferait une distinction entre les agrégats et les autres fonctions set, pour autant que je puisse voir qu'ils sont synonymes. Le morceau pertinent de la grammaire est ci-dessous.

6.5  <set function specification>

         Function

         Specify a value derived by the application of a function to an
         argument.

         Format

         <set function specification> ::=
                COUNT <left paren> <asterisk> <right paren>
              | <general set function>

         <general set function> ::=
                <set function type>
                    <left paren> [ <set quantifier> ] <value expression> <right paren>


         <set function type> ::=
              AVG | MAX | MIN | SUM | COUNT

         <set quantifier> ::= DISTINCT | ALL
Martin Smith
la source
9

Réponse rapide

"L'autre SET * est probablement lié aux anciennes versions de SQL Server.

J'avais l'habitude de le voir plus en arrière lorsque je travaillais avec SQL Server 6.5 et 7, je suis sûr, mais cela fait un certain temps. De nombreuses bizarreries ont été corrigées + SQL Server suit les normes plus

Plus long:

De nos jours, le message est contrôlé par SET ANSI_WARNINGSlequel par défaut ON.
Cela concerne uniquement

  • un avertissement est généré par une valeur NULL dans un agrégat.
  • une troncature silencieuse se produit lors de l'insertion / mise à jour des champs de type varchar

Un exemple:

DECLARE @foo TABLE (bar int NULL);
INSERT @foo VALUES (1), (2), (NULL);

SET ANSI_WARNINGS ON;
SELECT SUM(bar) FROM @foo;
SET ANSI_WARNINGS OFF;

SELECT SUM(bar) FROM @foo;

donne

(3 row(s) affected)
---- -----------
ON   3
Warning: Null value is eliminated by an aggregate or other SET operation.
(1 row(s) affected)
---- -----------
OFF  3
(1 row(s) affected)

Un autre exemple:

DECLARE @foo TABLE (bar varchar(5) NULL);
SET ANSI_WARNINGS ON;
INSERT @foo VALUES ('123456'); -- error
GO
DECLARE @foo TABLE (bar varchar(5) NULL);
SET ANSI_WARNINGS OFF;
INSERT @foo VALUES ('123456'); -- OK
GO

Personnellement, j'ignore l'avertissement et laisse SET ANSI_WARNINGS ON en raison des autres conséquences sur les colonnes calculées et les vues indexées de sa désactivation.

Enfin, il pourrait y avoir un déclencheur ou une colonne calculée ou une vue indexée générant cet avertissement quelque part

gbn
la source
La formulation du message d'erreur implique définitivement qu'il existe (ou existait) une opération non agrégée qui pourrait également éliminer les valeurs NULL pour moi.
Martin Smith
@Martin Smith: d'accord. Cela pourrait être indirect, mais selon ma (nouvelle) dernière déclaration. Ou une stratégie d'optimisation qui serait vue dans le plan
gbn
Dommage que les documents pour tout ce qui est plus ancien que SQL Server 7.0 ne semblent être en ligne nulle part.
Martin Smith
1
par exemple (difficile de trouver des trucs ce vieux): kbalertz.com/Feedback.aspx?kbNumber=149921/EN-US
GBN
1
Bien qu'en réalité, il semble que la version SQL Server 7.0 du message n'était qu'un avertissement: valeur nulle éliminée de l'agrégat. . Le SET operationbit n'a pas été ajouté avant 2000.
Martin Smith
2

L'autre côté de l'avertissement fait référence aux opérations 'set' et non aux opérations 'SET' - qui me semblent être un bug de message - par exemple, elles sont également produites avec des fonctions de fenêtrage:

select max(foo) over() as max_foo from (values (1), (2), (null)) as t(foo);
/*
max_foo
-------
2
2
2

Warning: Null value is eliminated by an aggregate or other SET operation.
*/
Jack Douglas
la source
1
Il semble que cela se réfère toujours à la partie d'agrégationMAX()
JNK
Est-ce que cela s'appelle la «partie d'agrégation»? Je sais ce que vous voulez dire, bien sûr, mais ce sont des opérations différentes - par exemple, comparer par select max(foo) from (values (1), (2), (null)) as t(foo) where 1=2;rapport àselect max(foo) over() from (values (1), (2), (null)) as t(foo) where 1=2;
Jack Douglas
2
C'est la fonction d'agrégation :) Je crois que l'erreur fait référence à MAX(). Je pense que votre deuxième exemple doit faire plus avec l'ordre des opérations à l'aide des fonctions de fenêtre.
JNK
ok - voyez ce que vous voulez dire des docs SS
Jack Douglas