SQL Server неверное имя столбца - PullRequest
       10

SQL Server неверное имя столбца

4 голосов
/ 03 августа 2011

Если я пытаюсь выполнить следующий код, я получаю ошибки

Сообщение 207, Уровень 16, Состояние 1, Строка 3 Недопустимое имя столбца «Другой».Сообщение 207, уровень 16, состояние 1, строка 4 Неверное имя столбца «Другой».

, хотя предикат для обоих операторов IF всегда оценивается как ложный.

CREATE TABLE #Foo (Bar INT)
GO
IF (1=0)
BEGIN
    SELECT Another FROM #Foo
END
GO
IF (1=0)
BEGIN
    ALTER TABLE #Foo ADD Another INT
    SELECT Another FROM #Foo 
END
GO
DROP TABLE #Foo

Это, вероятно, слишком упрощено ради примера;на самом деле мне нужно выбрать значения из столбца, но только если столбец существует.Если его не существует, мне все равно.В задаче, которая заставила меня задать этот вопрос, мой предикат соответствовал EXISTS (SELECT * FROM sys.columns WHERE object_id = @ID AND name = @Name).Есть ли способ достичь этого, не прибегая к моему заклятому врагу Dynamic SQL?Я понимаю, что мой SQL всегда должен быть правильно сформирован (то есть соответствовать грамматике) - даже в пределах блока, который никогда не выполняется - но я поражен тем, что я также вынужден сделать его семантически правильным!

РЕДАКТИРОВАТЬ: Хотя я не уверен, что приведенный ниже код добавляет много к коду выше, это еще один пример проблемы.В этом сценарии я только хочу установить значение Определенно (которое определенно существует в виде столбца) со значением Возможно (которое может существовать в виде столбца), если Возможно существует.

IF EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('dbo.TableName', 'U') AND name = 'Maybe')
BEGIN
    UPDATE dbo.TableName SET Definitely = Maybe
END

Ответы [ 5 ]

7 голосов
/ 03 августа 2011

SQL Server не выполняет построчно.Это не процедурный , как .net или Java-код.Таким образом, нет «невыполненного блока»

Пакет компилируется за один раз.На данный момент столбец не существует, но он знает, что таблица будет.Таблица не имеет столбца с именем «Другой».Сбой.

Точно так, как и ожидалось.

Теперь, какую реальную проблему вы пытаетесь решить?

Некоторые параметры:

  • 2 таблицы или одна таблица с обоими столбцами
  • использовать хранимые процедуры для разделения области действия
  • не использовать временные таблицы (может бытьне нужно, это может быть ваше процедурное мышление ...)
  • динамический SQL (из удаленного ответа Митча)

Редактировать после комментария;

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

4 голосов
/ 03 августа 2011

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

Например:

CREATE TABLE dbo.Test (definitely INT NOT NULL)
INSERT INTO dbo.Test (definitely) VALUES (1), (2), (3)

IF EXISTS (SELECT *
           FROM sys.columns
           WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
                 name = 'Maybe')
BEGIN
    EXEC('UPDATE dbo.Test SET definitely = maybe')
END

SELECT * FROM dbo.Test

ALTER TABLE dbo.Test ADD maybe INT NOT NULL DEFAULT 999

IF EXISTS (SELECT *
           FROM sys.columns
           WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
                 name = 'Maybe')
BEGIN
    EXEC('UPDATE dbo.Test SET definitely = maybe')
END

SELECT * FROM dbo.Test

DROP TABLE dbo.Test
2 голосов
/ 19 декабря 2012

Вы также можете попробовать Мартина Смита «Временное решение», используя несуществующую таблицу, чтобы получить «отложенное разрешение имен» для столбцов.

1 голос
/ 10 июля 2019

Получено из ответа @gbn.Чтобы решить эту проблему, я использовал «GO» между запросом ALTER и запросом, использующим столбец, добавленный ALTER.Это сделает 2 запроса для выполнения в виде отдельных пакетов, что обеспечит наличие столбца «Другой» перед запросом SELECT.

1 голос
/ 08 декабря 2013

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

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

С уважением, Chen

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