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

Почему что-то подобное не работает?

SELECT
CASE 
WHEN NULLIF(COL_LENGTH('Customers', 'Somecol'), '') IS NULL THEN NULL
ELSE Somecol
END AS MyTest
FROM Customers;

Я просто проверяю, существует ли столбец, однако SQL Server жалуется на отсутствие Somecol. Есть ли альтернатива этому в одном утверждении?

13 голосов | спросил Carson Reinke 6 J0000006Europe/Moscow 2014, 18:11:04

5 ответов


34

следующий запрос использует ту же идею как в этот удивительный ответ ypercube :

SELECT x.*
FROM (SELECT NULL AS SomeCol) AS dummy
CROSS APPLY
(
  SELECT
    ID,
    SomeCol AS MyTest
  FROM dbo.Customers
) AS x;

Он работает следующим образом:

  • if dbo.Customers имеет столбец с именем SomeCol, затем SomeCol в SomeCol AS MyTest будет разрешен как dbo.Customers.SomeCol;

  • , если таблица не имеет такого столбца, ссылка все равно будет действительна, потому что теперь она будет разрешена как dummy.SomeCol : dummy можно ссылаться в этом контексте.

Вы можете указать несколько «запасных» столбцов таким образом. Хитрость заключается не в том, чтобы использовать псевдоним таблицы для таких столбцов (что является практикой с нахмуренной практикой в ​​большинстве ситуаций, но в этом случае исключение псевдонима таблицы помогает вам решить проблему).

Если таблица используется в соединении, а другая таблица имеет свой собственный SomeCol, вам, вероятно, потребуется использовать вышеуказанный запрос как производную таблицу, прежде чем использовать ее в соединении, чтобы сохранить трюк, что-то вроде этого:

SELECT ...
FROM
(
  SELECT x.*
  FROM (SELECT NULL AS SomeCol) AS dummy
  CROSS APPLY (
    SELECT
      ID,
      SomeCol AS MyTest
    FROM dbo.Customers
  ) AS x
) AS cust
INNER JOIN ...
;
ответил Andriy M 6 J0000006Europe/Moscow 2014, 20:35:39
9

Один из способов сделать это - проверить существование столбцов, а затем построить динамический SQL на основе того, существует ли этот столбец.

Без динамического SQL SQL Server попытается оценить, существует ли столбец до того, как он даже выполнит учетную запись, что приведет к ошибке.

Однако это означает, что у вас будет 2 вопроса для написания и потенциального изменения в будущем. Но я не верю, что вы действительно должны ориентироваться на выражения SELECT для столбцов, которые могут не существовать.

declare @SQL varchar(max)

If exists (select 1 from sys.columns where Name = N'NameOfColumn' and object_id=object_id(N'yourTableName'))
begin
set @SQL = 'select ID, NameOfColumn from yourTableName'
exec(@sql)
end
else
begin
Print 'Column does not exist'
end
ответил Mark Sinkinson 6 J0000006Europe/Moscow 2014, 19:35:03
4

Вы можете использовать некоторый XML для запроса столбцов, которые могли бы быть в таблице.

Создайте XML из всех столбцов в строке в крестике и извлеките значение с помощью функции values().

В этом запросе идентификатор известен, поэтому получите его непосредственно из таблицы. Col1 и Col2 могут быть там или нет, поэтому получите их с помощью XML.

select T.ID,
       TX.X.value('(Col1/text())[1]', 'int') as Col1,
       TX.X.value('(Col2/text())[1]', 'int') as Col2
from T
  cross apply (select T.* for xml path(''), type) as TX(X)

SQL Fiddle

ответил Mikael Eriksson 6 J0000006Europe/Moscow 2014, 22:45:43
-1

Мой подход мало отличается от других. Я предпочитаю использовать систему для этого и просто получаю счет, потому что вы можете назначить количество столбцов переменной в верхней части запроса, а затем выбрать продолжить или не на основе этого. Недостатком этого является то, что у вас одинаковое имя столбца в нескольких таблицах, вы не уверены, что столбец существует в таблице, которую вы хотите запросить. Однако этот метод работает и с определенными таблицами, так как вы только хотите получить счет.

«Проблема» с просьбой об этом конкретно - проблема, с которой вы сталкиваетесь. В общем случае, если значение NULL вызывает проблемы, вы можете проверить другой способ проверки существования. Это один из способов сделать это, не рискуя нарушить работу сервера.

SELECT COUNT(*) FROM sys.columns WHERE sys.columns.name = 'FarmID'
ответил jinzai 6 J0000006Europe/Moscow 2014, 21:20:29
-1

Если я правильно понял ...

Вы можете использовать запрос, как показано ниже, и действовать соответственно на основе подсчета ... Если счетчик> 1, то это означает, что у вас есть col в этой таблице, а count = 0, тогда у вас нет этого col в этой таблице

Счетчик SELECT (*)
    ОТ ИНФОРМАЦИИ_SCHEMA.COLUMNS     WHERE COLUMN_NAME IN ('Id')
        AND TABLE_SCHEMA = 'dbo' и TABLE_NAME = 'UserBase';

ответил Sai 7 J0000006Europe/Moscow 2014, 01:03:24

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132