2016-02-17 3 views
0

Есть ли возможность изменить столбец с «Разрешает null» на «не разрешать null» без знания фактического типа данных столбца? неИзменение столбца (null -> not null) без знания типа данных

Я думаю, что нет, так что я сделал в качестве основного кода скелета для моей хранимой процедуры:

SELECT t.name,c.max_length FROM sys.types t 
LEFT JOIN sys.columns c ON(t.system_type_id = c.system_type_id) 
WHERE object_id=OBJECT_ID(@TableName) AND [email protected]; 

и

EXEC('UPDATE ' + @TableName + ' SET ' + @FieldName + ' = ' + @DefaultValue + ' WHERE ' + @FieldName + ' IS NULL'); 
EXEC('ALTER TABLE ' + @TableName + ' ALTER COLUMN ' + @FieldName + ' NOT NULL'); 

Я думаю, теперь я только должен получить возвращаемые значения из первый запрос обратно во второй. Я не могу понять, как получить значения в переменной, а затем снова получить к ним доступ. Идеи?

+0

Ваш первый запрос сломана. У вас есть переменные, застрявшие в середине строки ... если вы не используете параметризованный динамический sql. Настоящая проблема здесь заключается в том, что совсем не ясно, что вы пытаетесь сделать. И, конечно, вам не хватает еще одного логического элемента такого типа изменений. Вы пытаетесь установить столбец, чтобы он не разрешал значение null, но вы не проверяете, есть ли какие-либо строки с NULL для этого столбца. Если есть, это вызовет исключение. Возможно, объяснение требований в порядке. –

+0

С вашим последним правлением у вас все еще есть некоторые проблемы. Вы не можете просто установить для столбца значение null в инструкции alter. Он ДОЛЖЕН включать тип данных. –

+0

Я изменил свой вопрос, чтобы включить ваши предложения. Требование состоит в том, что я хочу сохранить тип данных в столбце, не зная, что это такое, но перед добавлением ПК установите столбец «не null». – Alexander

ответ

2

Поскольку INFORMATION_SCHEMA имеет всю необходимую информацию и является частью стандарта SQL, возможно, было бы лучше использовать это в этом случае (однако SQL-сервер ALTER TABLE ALTER COLUMN нестандартен, так что это может быть не так важно).

В любом случае, вы должны также проверить, указана ли длина символа и/или числовая точность, и убедитесь, что вы изменяете таблицу в правильной схеме (и не получаете dbo.TableName вместо customschema.TableName). Вы могли бы попробовать что-то вроде этого (я использовал INFORMATION_SCHEMA здесь, но вы можете легко реорганизовать это использовать sys.columns вид):

DECLARE @retVal VARCHAR(500); 
SELECT @retVal = 
    CASE WHEN CHARACTER_MAXIMUM_LENGTH > 0 
     THEN CONCAT(DATA_TYPE, '(', CHARACTER_MAXIMUM_LENGTH ,')') 
     WHEN CHARACTER_MAXIMUM_LENGTH = -1 AND DATA_TYPE <> 'xml' 
     THEN CONCAT(DATA_TYPE, '(MAX)') 
     WHEN DATA_TYPE IN ('numeric', 'decimal') 
     THEN CONCAT(DATA_TYPE, '(', NUMERIC_PRECISION,',', NUMERIC_SCALE,')') 
     ELSE DATA_TYPE 
     END 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_SCHEMA = @schemaName 
    AND TABLE_NAME = @tableName 
    AND COLUMN_NAME = @columnName 

@retVal теперь будет захватывать типы данных, как int, varchar(100), varbinary(MAX) или decimal(10,2) правильно.

А затем создать динамический SQL-запрос, как это:

DECLARE @sql VARCHAR(MAX); 
SET @sql = 'ALTER TABLE ' + @schemaName + '.' + @tableName + ' ALTER COLUMN ' + @columnName + ' ' + @retVal + ' NOT NULL;' 
EXEC(@sql); 
+1

В предыдущей версии этого сообщения неправильно предполагалось, что если NUMERIC_PRECISION не был NULL, тогда его нужно было указать - double проверил это, и это не является нулевым для 'int' и 'bigint' и т. Д. –

+0

. Я должен уважительно не соглашаться с тем, что вы должны используйте представления INFORMATION_SCHEMA вместо системных таблиц.Они в порядке для некоторых вещей, но они просто полностью пропускают ряд важных частей информации. Кажется, что Аарон Бертран согласен. http://sqlblog.com/blogs/aaron_bertrand/archive/2011/11/03/the-case-against-information-schema-views.aspx –

+0

В этом случае все необходимые данные присутствуют в INFORMATION_SCHEMA, и это должен улучшиться лучше, чем обновления sys. *. Но это не по своей сути неправильно использовать представления sys, и этот запрос, безусловно, может быть реорганизован, чтобы использовать их легко. –

3

Вы выбираете значения в переменные, как это:

SELECT @Var1=t.name,@Var2=c.max_length FROM sys.types t 
LEFT JOIN sys.columns c ON(t.system_type_id = c.system_type_id) 
WHERE object_id=OBJECT_ID(@TableName) AND [email protected]; 

Это, конечно, предполагает, что вы уже объявили var1 var2 &, и что ваш запрос будет возвращать только одну строку.

Смежные вопросы