3

SQLServer2008テーブルにカスタムdefault値があります。

これに似ています

CREATE DEFAULT [dbo].[Default_Timestamp]
AS 
   GetDate()

次に、そのデフォルトの値を変更します。

CREATE DEFAULT [dbo].[Default_Timestamp]
AS 
   GETUTCDATE()

既存のものを編集する前に、最初のものを削除して再作成する必要があります。

DROP DEFAULT [dbo].[Default_Timestamp]

次のエラーが発生します。

メッセージ3716、レベル16、状態3、4行
目デフォルトの「dbo.Default_Timestamp」は、1つ以上の列にバインドされているため、削除できません。

デフォルトはすでにいくつかのテーブルで使用されているため、新しいテーブルを削除して再作成することはできません。

再作成する前に、このデフォルトからすべてのテーブルのバインドを解除する必要があることはわかっています。

そのデフォルトにバインドされているすべてのテーブルと列を一覧表示するスクリプトを誰かが提供できますか?

4

4 に答える 4

4

これは複数のステップからなるプロセスです。

1)デフォルトのを見つけobject_idます:

DECLARE @DefaultObjectID INT
SELECT @DefaultObjectID = OBJECT_ID('Default_Timestamp')

2)そのデフォルトを参照するすべての列を検索します。

SELECT 
    ColumnName = c.Name,
    TableName = t.Name,
    UnbindCmd = 'EXEC sp_unbindefault ''' + t.Name + '.' + c.name + ''''
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE default_object_id = @DefaultObjectID

UnbindCmdこれにより、これらの列から実際にを削除するコマンドのリストが生成さDEFAULTれます。

3)次に、SQL Server Mgmt Studioウィンドウからその列をコピーし、新しいクエリウィンドウで実行して、これらすべての列からデフォルトを実際に「バインド解除」します。

4)新しいデフォルトを定義します

ただし、最近では、新しいもの自体を定義することはおそらくないでしょう。問題の列にデフォルトの制約を直接設定することはできませんか?DEFAULT

ALTER TABLE dbo.YourTable
ADD CONSTRAINT DF_YourTable_TimeStamp
DEFAULT GETUTCDATE() FOR YourColumnName

将来に向けて作業するのが簡単なようです!制約に明示的に名前を付けると、必要に応じて、その制約を簡単に見つけて再度削除することもできます。

于 2012-06-30T11:08:56.447 に答える
2

データベースでuses_ansi_nullsとuses_quoted_identifierをまとめて更新する必要がある古いスタイルのデフォルトをデータベースで見つけたときに、この問題に遭遇しました。

これは、古いスタイルのデフォルト(CREATE DEFAULT sp_BindDefault)を新しいスタイル(ALTER TABLE)に置き換えるために作成したコードです。

DECLARE @strSQL varchar(max)
        , @DBName varchar(50) = DB_NAME();

DROP TABLE IF EXISTS #tmp;

SELECT  IDENTITY(int, 1,1) AS ID,
        UnbindCmd = 'EXEC sp_unbindefault ''' + t.Name + '.' + c.name + ''';',
        DropCmd = 'DROP DEFAULT IF EXISTS [' + SCHEMA_NAME(SO.schema_id) + '].[' + OBJECT_NAME(SO.object_id) + '];',
        CreateCmd = 'ALTER TABLE [' + SCHEMA_NAME(t.Schema_id) + '].[' + t.Name + ']'
                    + ' ADD CONSTRAINT df_' + REPLACE(t.Name, ' ', '') + '_' + REPLACE(c.Name, ' ', '')
                    + ' DEFAULT (' + RIGHT(m.definition, LEN(m.definition) - CHARINDEX(' AS ', m.definition) - 3)
                    + ') FOR ' + QUOTENAME(c.Name) + ';'
INTO    #tmp
FROM    sys.sql_modules m
        join sys.columns c on c.default_object_id = m.object_id
        INNER JOIN sys.tables t ON c.object_id = t.object_id
        JOIN sys.objects SO ON SO.object_id = C.default_object_id
WHERE   (m.uses_ansi_nulls = 0 
        OR m.uses_quoted_identifier = 0)
ORDER BY
        t.name
        , c.name;

BEGIN TRANSACTION
    BEGIN TRY
        DECLARE UnbindCursor CURSOR LOCAL FAST_FORWARD
        FOR SELECT  UnbindCmd
            FROM    #tmp
            ORDER BY
                    ID;

        OPEN UnbindCursor;

        FETCH NEXT FROM UnbindCursor INTO @strSQL;

        WHILE @@FETCH_STATUS = 0
            BEGIN
                EXEC (@strSQL);

                FETCH NEXT FROM UnbindCursor INTO @strSQL;
            END

        CLOSE UnbindCursor;
        DEALLOCATE UnbindCursor;

        DECLARE DropCursor CURSOR LOCAL FAST_FORWARD
        FOR SELECT  DropCmd
            FROM    #tmp
            GROUP BY
                    DropCmd
            ORDER BY
                    MIN(id)

        OPEN DropCursor;

        FETCH NEXT FROM DropCursor INTO @strSQL;

        WHILE @@FETCH_STATUS = 0
            BEGIN
                EXEC (@strSQL);

                FETCH NEXT FROM DropCursor INTO @strSQL;
            END

        CLOSE DropCursor;
        DEALLOCATE DropCursor;

        DECLARE CreateCursor CURSOR LOCAL FAST_FORWARD
        FOR SELECT  CreateCmd
            FROM    #tmp
            ORDER BY
                    id

        OPEN CreateCursor;

        FETCH NEXT FROM CreateCursor INTO @strSQL;

        WHILE @@FETCH_STATUS = 0
            BEGIN
                EXEC (@strSQL);

                FETCH NEXT FROM CreateCursor INTO @strSQL;
            END

        CLOSE CreateCursor;
        DEALLOCATE CreateCursor;

        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMessage nvarchar(4000)
                , @ErrorSeverity int
                , @ErrorState int;

        SELECT   
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),  
            @ErrorState = ERROR_STATE();  

        IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;

        RAISERROR (@ErrorMessage, -- Message text.  
                    @ErrorSeverity, -- Severity.  
                    @ErrorState -- State.  
                    );  
    END CATCH
于 2019-12-03T16:00:10.453 に答える
1

CREATEDEFAULTまたはDROPDEFAULTをスタンドアロンコマンドとして見たことはありませんが、デフォルトの制約を追加または削除するCONSTRAINT句しか知りません。

SSMS 2008は、次のコードを生成します(テーブルデザイナーで右クリックして、「変更スクリプトを生成...」)。

ALTER TABLE dbo.T ADD CONSTRAINT
    DF_T_DateTimeColumn DEFAULT getdate() FOR DateTimeColumn
GO

ALTER TABLE dbo.T
    DROP CONSTRAINT DF_T_DateTimeColumn
GO
ALTER TABLE dbo.T ADD CONSTRAINT
    DF_T_DateTimeColumn DEFAULT getutcdate() FOR DateTimeColumn
GO

アップデート:

私はそれを認めます、私はEXEC sp_bindefaultを使用したことはありませんが、MSDNが言うように、その使用は推奨されていないと思います。

この機能は、MicrosoftSQLServerの将来のバージョンで削除される予定です。この機能を新しい開発作業で使用しないでください。また、現在この機能を使用しているアプリケーションをできるだけ早く変更してください。代わりに、ALTERTABLEまたはCREATETABLEステートメントのDEFAULTキーワードを使用してデフォルト定義を作成することをお勧めします。

もちろん、これはsp_unbindefaultにも当てはまります。

于 2012-06-30T11:07:25.277 に答える
1

default_object_id次の場所を見ると、デフォルトのオブジェクトを使用している列を見つけることができますsys.columns

スタンドアロンオブジェクトsys.sp_bindefaultであるか、インラインの列レベルのDEFAULT制約であるかに関係なく、デフォルトオブジェクトのID。

これを知っていると、デフォルトオブジェクトからすべての列のバインドを解除し、デフォルトを制約ベースのデフォルト値に置き換えるスクリプトを作成するのは簡単です。

use master;
go

if db_id('test') is not null
    drop database test;
go

create database test;
go

use test;
go

create default foo as 1;
go

create table t1 (a int);
create table t2 (b int);
go

exec sp_bindefault 'foo', 't1.a';
exec sp_bindefault 'foo', 't2.b';
go

drop default foo;
-- Msg 3716, Level 16, State 3, Line 2
-- The default 'foo' cannot be dropped because it is bound to one or more column.
go

declare crs cursor static forward_only read_only for
select object_schema_name(object_id) as schema_name,
        object_name(object_id) as object_name,
        name as column_name
    from sys.columns where default_object_id = object_id('foo');
open crs;

declare @schema_name sysname, @object_name sysname, @column_name sysname, @sql nvarchar(max);

fetch next from crs into @schema_name, @object_name, @column_name;
while @@fetch_status = 0
begin
    set @sql = N'exec sp_unbindefault ' + quotename(
        quotename(@schema_name) + N'.'+
        quotename(@object_name) + N'.'+
        quotename(@column_name), '''');
    print @sql;
    exec sp_executesql @sql;
    set @sql = N'alter table ' +
        quotename(@schema_name) + N'.' + 
        quotename(@object_name) + N' add constraint ' + 
        quotename(N'default_' + @column_name) + N' default 2 for ' +
        quotename(@column_name);
    print @sql;
    exec sp_executesql @sql;
    fetch next from crs into @schema_name, @object_name, @column_name;
end

close crs;
deallocate crs;
go

drop default foo;
-- it now succeeds
go
于 2012-06-30T11:37:02.180 に答える