web-dev-qa-db-fra.com

Comportements étranges avec options définies dans SSMS

J'échège l'effet de diverses options définies sur la création de vues indexées sur SQL Server 2014 CU1. Le code suivant:

  1. veille à ce que les options définies soient telles qu'elles doivent être
  2. crée une table
  3. crée une vue basée sur la table
  4. crée un index sur la vue
  5. insère un enregistrement dans la vue (qui échouera si les options définies sont incorrectes)

Cela fonctionne comme prévu. Toutefois, si je ne justifie pas la section où je définirai délibérément chaque option définie sur la mauvaise valeur, l'instruction Créer une index (qui se produit antérieure dans le script) échoue à ce que cité_dentifiant a la valeur erronée.

J'ai testé avec SSMS 2012 et 2014. Comment cela peut-il être?

USE tempdb;

-- ensure correct SET options for indexed view creation
-- http://msdn.Microsoft.com/en-us/library/ms191432.aspx
SET ANSI_NULLS  ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET NUMERIC_ROUNDABORT OFF;
SET QUOTED_IDENTIFIER ON;

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.VIEWS
            WHERE TABLE_NAME = 'v1'
            AND TABLE_SCHEMA = 'dbo')
    DROP VIEW dbo.v1;
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES
            WHERE TABLE_NAME = 't1'
            AND TABLE_SCHEMA = 'dbo')
    DROP TABLE t1;
CREATE TABLE dbo.t1(c1 int);
GO
CREATE VIEW dbo.v1 WITH SCHEMABINDING AS SELECT c1 FROM dbo.t1;
GO
CREATE UNIQUE CLUSTERED INDEX i1 ON dbo.v1(c1);

---- make SET options the opposite of what is required
--SET ANSI_NULLS    OFF;
--SET ANSI_PADDING  OFF;
--SET ANSI_WARNINGS OFF;
--SET ARITHABORT    OFF;
--SET CONCAT_NULL_YIELDS_NULL   OFF;
--SET NUMERIC_ROUNDABORT    ON;
--SET QUOTED_IDENTIFIER OFF;

INSERT INTO dbo.v1(c1) VALUES(1);

DROP VIEW dbo.v1;
DROP TABLE dbo.t1;

Je peux y travailler avec SQL dynamique et obtenir le message d'erreur attendu:

MSG 1934, Niveau 16, State 1, Line 32 Insérer a échoué car les options de définition suivantes ont des paramètres incorrects: "citer_identifier" ...

-- make SET options the opposite of what is required
EXECUTE ('SET ANSI_NULLS    OFF;
SET ANSI_PADDING    OFF;
SET ANSI_WARNINGS   OFF;
SET ARITHABORT  OFF;
SET CONCAT_NULL_YIELDS_NULL OFF;
SET NUMERIC_ROUNDABORT  ON;
SET QUOTED_IDENTIFIER   OFF;
INSERT INTO dbo.v1(c1) VALUES(1);');

mais pourquoi devrais-je avoir à?

4
Colin Daley

Parmi les instructions définies de votre script, définissez cible_Identifier est spécial en ce sens qu'elle est traitée au temps d'analyse plutôt qu'au moment exécuté.

De - Définir des instructions (transact-sql) (emphasis mine):

Considérations lorsque vous utilisez les instructions définies

  • Toutes les instructions définies sont implémentées à l'exécution ou à l'exécution du temps, à l'exception de la définition FIPS_FLAGGUSG, définissez les décalagests, définissez parsonly, et définissez cité_dentifier. Ces affirmations sont implémentées au moment de l'analyse.

Confirmé dans SET CUTED_Identifier (Transact-SQL) :

Remarques

[...]

SET CUTED_Identifier est défini à l'heure d'analyse. [...]

Donc, dans votre cas cied_Identifier reçoit la réinitialisation à l'heure d'analyse et, par conséquent, éteint à l'époque, l'index est exécuté. Le moteur se plaint à ce sujet comme prévu.

Pour résoudre ce problème, vous n'avez pas à recourir à Dynamic SQL, il suffit de mettre une ligne GO juste après l'instruction Créer une index pour en faire un lot différent des ensembles suivants, ce qui le causerait de être analysé séparément d'eux:

…

CREATE UNIQUE CLUSTERED INDEX i1 ON dbo.v1(c1);

GO

-- make SET options the opposite of what is required
SET ANSI_NULLS    OFF;
SET ANSI_PADDING  OFF;
SET ANSI_WARNINGS OFF;
SET ARITHABORT    OFF;
SET CONCAT_NULL_YIELDS_NULL   OFF;
SET NUMERIC_ROUNDABORT    ON;
SET QUOTED_IDENTIFIER OFF;

…

Notez cependant que Définition des instructions (transact-sql) inclut également les éléments suivants (mettant l'accent sur la mine):

Considérations lorsque vous utilisez les instructions définies

[...]

  • Lorsque vous créez et manipulez des index sur des colonnes calculées ou des vues indexées, les options de jeu Arithabort, Concat_Null_Yields_Null, cité_dentifiant, ANSI_NULLS, ANSI_PADDING et ANSI_WARNINGS doivent être définies sur ON. L'option numeric_roundabort doit être définie sur OFF.

    Si l'une de ces options n'est pas définie sur les valeurs requises, l'insertion, la mise à jour, la mise à jour, les actions à checkdb DBCC et DBCC sur des vues indexées ou des tables avec des index sur colonnes calculées échouera. SQL Server sélectionnera une erreur d'erreur toutes les options de manière incorrecte. En outre, SQL Server traitera des instructions de sélection sur ces tables ou des vues indexées comme si les index des colonnes calculées ou sur les vues n'existent pas.

Ce qui signifie que les instructions définies de manière non motivée briseraient toujours votre script, il n'y a que de ne pas créer d'index mais à l'insert.

4
Andriy M