13 votes

Pourquoi MS SQL vous permet-il de créer une colonne illégale ?

J'ai récemment vu un tweet affirmant que vous pouviez empêcher d'autres développeurs de lire un tableau en utilisant la fonction SELECT * FROM TableName en construisant votre tableau de la manière suivante :

CREATE TABLE [TableName]
(
   [ID] INT IDENTITY NOT NULL,
   [Name] VARCHAR(50) NOT NULL,
   [DontUseStar] AS (1 / 0)
);

Il est facile de voir que l'utilisation du SELECT * ici, on essaierait de lire le nom de la colonne vide comme 1 divisé par 0 (ce qui provoquerait une erreur de division par zéro), mais sans qu'un type de données soit attribué à la colonne.

Pourquoi SQL vous permet-il de créer une colonne sans type de données assigné, avec un nom dont il sait qu'il sera illégal ?

10voto

Daniel N Points 723

C'est une syntaxe parfaitement valide pour une colonne calculée. Les colonnes calculées peuvent être utilisées pour calculer une certaine valeur lors de la sélection sans les stocker réellement, bien que la valeur puisse être persistée.

La raison pour laquelle 1/0 est autorisé, est que la valeur réelle de la colonne calculée n'est pas évaluée avant l'exécution. Par exemple, la colonne calculée peut être définie comme columna/columnb, la même erreur se produira si une ligne de columnb a un 0 et est , mais seulement si cette ligne/colonne a été sélectionnée.

if object_id('tempdb..#t') IS NOT NULL
    drop table #t;

CREATE TABLE #t 
(a int
,b int
,div as (a/b)
);

INSERT INTO #t
values 
(1,1)
,(2,0);

SELECT * FROM #t WHERE a = 1;
SELECT a from #t; -- NO ERRORS

SELECT * FROM #t WHERE a=2; --WILL RESULT IN AN ERROR
SELECT * FROM #t; --WILL RESULT IN AN ERROR

https://docs.microsoft.com/en-us/sql/relational-databases/tables/specify-computed-columns-in-a-table?view=sql-server-2017

7voto

Gordon Linoff Points 213350

Ce que vous avez créé est un colonne calculée et il est assez puissant et utile !

L'expression peut être n'importe quoi. Par exemple, vous pouvez définir :

CREATE TABLE [TableName] (
   [ID] INT IDENTITY NOT NULL,
   [Name] VARCHAR(50) NOT NULL,
   NameLength as (LEN(Name))
);

Cela créerait une colonne appelée NameLength et il aura toujours la longueur de Name quand vous y faites référence non update pas de déclencheurs, pas de vues. Cela fonctionne tout simplement.

Vous n'avez pas besoin d'un type car le serveur SQL peut le déterminer.

L'erreur que vous avez peut même être bénéfique -- si vous realmente vous voulez faire en sorte que les utilisateurs n'utilisent jamais select * .

-1voto

Serg Points 7780

Je pense que c'est une excellente façon de créer un tableau qui ne permet pas de sélectionner des lignes. select * from . Pourquoi peut-on avoir besoin d'une telle table ? Qui sait, probablement pour y connecter un déclencheur INSTEAD OF ou autre. N'importe quel langage de programmation permet de coder comme suit x=1/0 Ce n'est pas au compilateur de décider pourquoi on en a besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X