SQL Server 2008でデフォルトの制約が設定されている列を削除するにはどうすればよいですか?
私のクエリは
alter table tbloffers
drop column checkin
エラーが発生しています
1つ以上のオブジェクトがこの列にアクセスするため、ALTER TABLE DROP COLUMNチェックインが失敗しました。
誰でも私のクエリを修正して、制約付きの列を削除できますか?
SQL Server 2008でデフォルトの制約が設定されている列を削除するにはどうすればよいですか?
私のクエリは
alter table tbloffers
drop column checkin
エラーが発生しています
1つ以上のオブジェクトがこの列にアクセスするため、ALTER TABLE DROP COLUMNチェックインが失敗しました。
誰でも私のクエリを修正して、制約付きの列を削除できますか?
回答:
最初に問題のあるものを削除する必要がありますDEFAULT constraint
。その後、列を削除できます
alter table tbloffers drop constraint [ConstraintName]
go
alter table tbloffers drop column checkin
しかし、エラーは他の理由から表示される可能性があります-たとえば、ユーザーが定義したSCHEMABINDING
オプションやオプションが設定されたビュー。
UPD: 完全に自動化された制約の削除スクリプト:
DECLARE @sql NVARCHAR(MAX)
WHILE 1=1
BEGIN
SELECT TOP 1 @sql = N'alter table tbloffers drop constraint ['+dc.NAME+N']'
from sys.default_constraints dc
JOIN sys.columns c
ON c.default_object_id = dc.object_id
WHERE
dc.parent_object_id = OBJECT_ID('tbloffers')
AND c.name = N'checkin'
IF @@ROWCOUNT = 0 BREAK
EXEC (@sql)
END
次に、最初に別のクエリを実行して制約名を取得する必要なしに、名前が不明なデフォルト制約を削除する別の方法を示します。
DECLARE @ConstraintName nvarchar(200)
SELECT @ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS
WHERE PARENT_OBJECT_ID = OBJECT_ID('__TableName__')
AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns
WHERE NAME = N'__ColumnName__'
AND object_id = OBJECT_ID(N'__TableName__'))
IF @ConstraintName IS NOT NULL
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)
列とその制約を個別にではなく1つのステートメントで削除することもできます。
CREATE TABLE #T
(
Col1 INT CONSTRAINT UQ UNIQUE CONSTRAINT CK CHECK (Col1 > 5),
Col2 INT
)
ALTER TABLE #T DROP CONSTRAINT UQ ,
CONSTRAINT CK,
COLUMN Col1
DROP TABLE #T
(ただし、外部キー、一意の主キー制約、計算された列、インデックスなどの他の可能な列の依存関係はありません)
CREATE TABLE [dbo].[TestTable]
(
A INT DEFAULT '1' CHECK (A=1),
B INT,
CHECK (A > B)
)
GO
DECLARE @TwoPartTableNameQuoted nvarchar(500) = '[dbo].[TestTable]',
@ColumnNameUnQuoted sysname = 'A',
@DynSQL NVARCHAR(MAX);
SELECT @DynSQL =
'ALTER TABLE ' + @TwoPartTableNameQuoted + ' DROP' +
ISNULL(' CONSTRAINT ' + QUOTENAME(OBJECT_NAME(c.default_object_id)) + ',','') +
ISNULL(check_constraints,'') +
' COLUMN ' + QUOTENAME(@ColumnNameUnQuoted)
FROM sys.columns c
CROSS APPLY (SELECT ' CONSTRAINT ' + QUOTENAME(OBJECT_NAME(referencing_id)) + ','
FROM sys.sql_expression_dependencies
WHERE referenced_id = c.object_id
AND referenced_minor_id = c.column_id
AND OBJECTPROPERTYEX(referencing_id, 'BaseType') = 'C'
FOR XML PATH('')) ck(check_constraints)
WHERE c.object_id = object_id(@TwoPartTableNameQuoted)
AND c.name = @ColumnNameUnQuoted;
PRINT @DynSQL;
EXEC (@DynSQL);
DROP CONSTRAINT
文法を確認するには、これは必須の引数です。制約に明示的に名前を付けない場合は、そのために生成されたSQL Serverの名前を調べる必要があります(例:marcの回答に従って)。しかし、それでも、制約と列を同時に削除できることがわかりました。
このクエリでデフォルトの制約をここで見つけます:
SELECT
df.name 'Constraint Name' ,
t.name 'Table Name',
c.NAME 'Column Name'
FROM sys.default_constraints df
INNER JOIN sys.tables t ON df.parent_object_id = t.object_id
INNER JOIN sys.columns c ON df.parent_object_id = c.object_id AND df.parent_column_id = c.column_id
これにより、デフォルトの制約の名前と、テーブルおよび列の名前がわかります。
その情報を入手したら、最初にデフォルトの制約を削除する必要があります。
ALTER TABLE dbo.YourTable
DROP CONSTRAINT name-of-the-default-constraint-here
そして、あなたは列をドロップすることができます
ALTER TABLE dbo.YourTable DROP COLUMN YourColumn
ALTER TABLE table DROP CONSTRAINT DF_XY DROP COLUMN XY
残念ながら、このステートメントの構文は正しくありません
DROP
してこれを機能させる必要があります
以下はSQL Azureバックエンド(SQL Server Management Studioを使用)に対して私のために機能したので、YMMVですが、それが機能する場合、他のソリューションよりも簡単です。
ALTER TABLE MyTable
DROP CONSTRAINT FK_MyColumn
CONSTRAINT DK_MyColumn
-- etc...
COLUMN MyColumn
GO
私は同じを得た:
1つ以上のオブジェクトがこの列メッセージにアクセスするため、ALTER TABLE DROP COLUMNが失敗しました。
私の列には、最初に削除する必要があるインデックスがありました。sys.indexesを使用してトリックを行いました:
DECLARE @sql VARCHAR(max)
SELECT @sql = 'DROP INDEX ' + idx.NAME + ' ON tblName'
FROM sys.indexes idx
INNER JOIN sys.tables tbl ON idx.object_id = tbl.object_id
INNER JOIN sys.index_columns idxCol ON idx.index_id = idxCol.index_id
INNER JOIN sys.columns col ON idxCol.column_id = col.column_id
WHERE idx.type <> 0
AND tbl.NAME = 'tblName'
AND col.NAME = 'colName'
EXEC sp_executeSql @sql
GO
ALTER TABLE tblName
DROP COLUMN colName
スクリプトをSQLサーバーのバージョンに少し更新しました
DECLARE @sql nvarchar(max)
SELECT @sql = 'ALTER TABLE `table_name` DROP CONSTRAINT ' + df.NAME
FROM sys.default_constraints df
INNER JOIN sys.tables t ON df.parent_object_id = t.object_id
INNER JOIN sys.columns c ON df.parent_object_id = c.object_id AND df.parent_column_id = c.column_id
where t.name = 'table_name' and c.name = 'column_name'
EXEC sp_executeSql @sql
GO
ALTER TABLE table_name
DROP COLUMN column_name;
列の削除を妨げるのは常にデフォルトの制約だけではなく、インデックスによって制約の削除が妨げられる場合もあります。そのため、列のインデックスまたは制約を削除し、最後にそれ自体を削除する手順を記述しました。
IF OBJECT_ID ('ADM_delete_column', 'P') IS NOT NULL
DROP procedure ADM_delete_column;
GO
CREATE procedure ADM_delete_column
@table_name_in nvarchar(300)
, @column_name_in nvarchar(300)
AS
BEGIN
/* Author: Matthis (matthis@online.ms at 2019.07.20)
License CC BY (creativecommons.org)
Desc: Administrative procedure that drops columns at MS SQL Server
- if there is an index or constraint on the column
that will be dropped in advice
=> input parameters are TABLE NAME and COLUMN NAME as STRING
*/
SET NOCOUNT ON
--drop index if exist (search first if there is a index on the column)
declare @idx_name VARCHAR(100)
SELECT top 1 @idx_name = i.name
from sys.tables t
join sys.columns c
on t.object_id = c.object_id
join sys.index_columns ic
on c.object_id = ic.object_id
and c.column_id = ic.column_id
join sys.indexes i
on i.object_id = ic.object_id
and i.index_id = ic.index_id
where t.name like @table_name_in
and c.name like @column_name_in
if @idx_name is not null
begin
print concat('DROP INDEX ', @idx_name, ' ON ', @table_name_in)
exec ('DROP INDEX ' + @idx_name + ' ON ' + @table_name_in)
end
--drop fk constraint if exist (search first if there is a constraint on the column)
declare @fk_name VARCHAR(100)
SELECT top 1 @fk_name = CONSTRAINT_NAME
from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
where TABLE_NAME like @table_name_in
and COLUMN_NAME like @column_name_in
if @fk_name is not null
begin
print concat('ALTER TABLE ', @table_name_in, ' DROP CONSTRAINT ', @fk_name)
exec ('ALTER TABLE ' + @table_name_in + ' DROP CONSTRAINT ' + @fk_name)
end
--drop column if exist
declare @column_name VARCHAR(100)
SELECT top 1 @column_name = COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME like concat('%',@column_name_in,'%')
if @column_name is not null
begin
print concat('ALTER TABLE ', @table_name_in, ' DROP COLUMN ', @column_name)
exec ('ALTER TABLE ' + @table_name_in + ' DROP COLUMN ' + @column_name)
end
end;
GO
--to run the procedure use this execute and fill the parameters
execute ADM_delete_column
@table_name_in = ''
, @column_name_in = ''
;