Почему MS SQL позволяет создавать недопустимые столбцы? - PullRequest
12 голосов
/ 30 мая 2019

Недавно я увидел твит, в котором говорится, что вы можете запретить другим разработчикам читать из таблицы, используя SELECT * FROM TableName, скомпилировав вашу таблицу следующим образом:

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

Легко видеть, что с помощьюSELECT * здесь будет пытаться прочитать пустое имя столбца как 1, деленное на 0 (таким образом, вызывая ошибку деления на ноль), но без типа данных, назначенного столбцу.

Почему SQL позволяет создаватьстолбец без назначенного типа данных с именем, которое он знает, будет недопустимым?

Ответы [ 3 ]

10 голосов
/ 30 мая 2019

Это совершенно правильный синтаксис для вычисляемого столбца.Вычисляемые столбцы могут использоваться для вычисления некоторого значения при выборе без фактического сохранения их, хотя это значение может быть сохранено.

Причина, по которой 1/0 допускается, заключается в том, что фактическое вычисленное значение столбца не оценивается до времени выполнения.Например, вычисляемый столбец может быть определен как columna / columnb, такая же ошибка произойдет, если какая-либо строка в columnb имеет 0 и есть, но только если была выбрана эта строка / столбец.

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

7 голосов
/ 30 мая 2019

Вы создали вычисляемый столбец , и он достаточно мощный и полезный!

Выражение может быть любым.Например, вы можете определить:

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

Это создаст столбец с именем NameLength, и он всегда будет иметь длину Name, когда вы ссылаетесь на него - нет update s, неттриггеры, нет просмотров.Это просто работает.

Вам не нужен тип, потому что SQL Server может это выяснить.

Имеющаяся у вас ошибка может быть даже полезной - если вы действительно хочу обеспечить, чтобы пользователи никогда не использовали select *.

0 голосов
/ 30 мая 2019

Я думаю, что это отличный способ создать таблицу, которая не позволяет выбирать строки select * from.Зачем нужен такой стол?Кто знает, возможно, подключить триггер INSTEAD OF к этому или что-то.Любой язык программирования допускает такой код, как x=1/0, решать, зачем он нужен, не дело компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...