74

別のデータベースと比較するために、いくつかのデータを含むデータベースをインポートしました。

ターゲット データベースには照合がLatin1_General_CI_ASあり、ソース データベースには がありSQL_Latin1_General_CP1_CI_ASます。

一般的に、ソース データベースの照合順序をLatin1_General_CI_ASSQL Server Management Studio を使用するように変更しました。ただし、内部のテーブルと列は古い照合のままです。

次を使用して列を変更できることを知っています。

ALTER TABLE [table] 
ALTER COLUMN [column] VARCHAR(100) COLLATE Latin1_General_CI_AS

しかし、すべてのテーブルと内部のすべての列に対してこれを行う必要があります。

私が知る前に、すべてのテーブルとタイプのすべての列を読み取りvarchar、テーブルと列のカーソルループでそれらを変更するストアドプロシージャの作成を開始します...

誰かがより簡単な方法を知っていますか、またはプロシージャ内のすべてのテーブルを実行するスクリプトでこれを行う唯一の方法ですか?

4

12 に答える 12

81

適切な方法が見つからなかったので、それを行うためのスクリプトを作成し、必要な人のためにここで共有しています。スクリプトはすべてのユーザー テーブルで実行され、列が収集されます。列の型が任意の char 型の場合、指定された照合順序に変換しようとします。

これが機能するには、列にインデックスと制約がない必要があります。

誰かがまだこれに対するより良い解決策を持っている場合は、投稿してください!

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table)
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF (@max_length = -1) OR (@max_length > 4000) SET @max_length = 4000;

        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or constraint rely on the column' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO
于 2013-08-08T10:16:35.270 に答える
40

ここでも、私は答えに満足していません。私は JIRA 6.4.x を JIRA Software 7.x にアップグレードする任務を負い、データベースと列の照合に関する特定の問題に取り組みました。

SQL Server では、主キーや外部キー、さらにはインデックスなどの制約を削除しないと、上記の回答として提供されたスクリプトはまったく機能しません。ただし、それらのプロパティのないものは変更されます。すべての制約を手動で削除して再度作成したくないため、これは非常に問題です。その操作はおそらくエラーで終わる可能性があります。一方、変更を自動化するスクリプトを作成するには、時間がかかる場合があります。

そこで、SQL Management Studio を使用して簡単に移行する方法を見つけました。手順は次のとおりです。

  • データベースの名前を別の名前に変更します。たとえば、私のは「Jira」だったので、「JiraTemp」という名前に変更しました。
  • 「Jira」という名前の新しいデータベースを作成し、正しい照合順序を設定してください。「オプション」ページを選択して、照合順序を変更するだけです。
  • 作成したら、「JiraTemp」に戻り、右クリックして「タスク -> スクリプトの生成...」を選択します。
    • 「データベース全体とすべてのデータベース オブジェクトをスクリプト化する」を選択します。
    • [新しいクエリ ウィンドウに保存] を選択し、[詳細設定] を選択します。
    • 「サーバーバージョンのスクリプト」の値を目的の値に変更します
    • 「スクリプト オブジェクト レベルのアクセス許可」、「スクリプト所有者」、および「スクリプト フルテキスト インデックス」を有効にします。
    • 他のすべてはそのままにするか、必要に応じてカスタマイズします。
  • 生成されたら、「CREATE DATABASE」セクションを削除します。「JiraTemp」を「Jira」に置き換えます。
  • スクリプトを実行します。データベース全体の構造とデータベースの権限が "Jira" にレプリケートされるようになりました。
  • データをコピーする前に、すべての制約を無効にする必要があります。データベース「Jira」で次のコマンドを実行します。EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
  • ここで、データを転送する必要があります。これを行うには、"JiraTemp" を右クリックし、[タスク -> データのエクスポート...] を選択します。
    • OLE DB Provider for SQL Server をデータ ソースおよび宛先として選択します。
    • ソース データベースは「JiraTemp」
    • 宛先データベースは「Jira」
    • サーバー名は、送信元と送信先で技術的に同じです (別のサーバーにデータベースを作成した場合を除く)。
    • 「1 つまたは別のテーブルまたはビューからデータをコピーする」を選択します。
    • ビュー以外のすべてのテーブルを選択します。次に、まだ強調表示されている場合は、[マッピングの編集] をクリックします。「ID挿入を有効にする」にチェックを入れます
    • [OK]、[次へ]、[完了] の順にクリックします
  • データ転送には時間がかかる場合があります。完了したら、次のコマンドを実行してすべての制約を再度有効にします。exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

完了したら、JIRA を再起動しました。データベースの照合順序が整いました。多くの人に役立つことを願っています!

于 2016-02-03T15:02:30.140 に答える
17

長さの問題 nvarchar を修正し、NULL/NOT NULL を追加

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
DECLARE @is_Nullable bit;
DECLARE @null nvarchar(25);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
        , c.is_nullable
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table)
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF (@max_length = -1) SET @max_length = 4000;
        set @null=' NOT NULL'
        if (@is_nullable = 1) Set @null=' NULL'
        if (@Data_type='nvarchar') set @max_length=cast(@max_length/2 as bigint)
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + rtrim(@column_name) + '] ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) +  ') COLLATE ' + @collate + @null
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or contraint rely on the column ' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_Nullable

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO
于 2014-01-31T10:55:41.827 に答える
5

これを行うには、私に合った簡単な解決策があります。

  1. 新しい照合順序で新しいデータベースを作成します。
  2. 元のデータベースのデータをスクリプト モードでエクスポートします。
  3. スクリプトを使用してコンテンツを新しいデータベースにインポートします (USE 文の名前を新しいデータベースに変更します)。

ただし、データベースにトリガー、プロシージャー、または同様のものがある場合は注意が必要です。これは、データとテーブルだけではありません。

于 2015-02-15T21:08:14.630 に答える
5

スクリプトを少し変更しました。

DECLARE @collate nvarchar(100);
DECLARE @table sysname;
DECLARE @schema sysname;
DECLARE @objectId int;
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
DECLARE @is_Nullable bit;
DECLARE @null nvarchar(25);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT tbl.TABLE_SCHEMA,[name],obj.id
FROM sysobjects as obj
inner join INFORMATION_SCHEMA.TABLES as tbl
on obj.name = tbl.TABLE_NAME
WHERE OBJECTPROPERTY(obj.id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @schema, @table, @objectId;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE local_change_cursor CURSOR FOR
    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
        , c.is_nullable
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = @objectId
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (@max_length = -1) SET @max_length = 4000;
        set @null=' NOT NULL'
        if (@is_nullable = 1) Set @null=' NULL'
        if (@Data_type='nvarchar') set @max_length=cast(@max_length/2 as bigint)
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @schema + '.' + @table + ' ALTER COLUMN [' + rtrim(@column_name) + '] ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) +  ') COLLATE ' + @collate + @null
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or contraint rely on the column ' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_Nullable

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @schema,@table,@objectId

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO
于 2020-05-26T19:07:15.993 に答える
0

すべてのフィールドを含むデータベースの照合順序を変更する最も簡単な方法は、マージ レプリケーションよりも優れています。

  • ターゲット照合でサーバーを取得します (サーバー照合プロップ)
  • 古いサーバーでマージ パブリケーションを作成する
  • ソース データベースのすべての製品をパブリケーションに追加します
  • snapsoht エージェントを実行し、完了するのを待ちます
  • nice 照合順序でサーバーを対象とするパブリケーションにプッシュ サブスクリプションを追加します。
  • サブスクリプションの初期化
  • レプリケーション モニターにチェックインし、エージェントの準備が整うまで待ちます
  • サブスクリプションを削除
  • パブリケーションの削除

次のsql スクリプトは、ユーザー テーブルのマージ パブリケーションを作成します。Managemet Studio で行う他の手順と、ストアド プロシージャ、ビューなどのスクリプト オブジェクトを後続の手順で別のスクリプトを使用して作成します。

ALTER PROCEDURE [dbo].[CreateMergePublication]
    @PublicationName nvarchar(max) = N'Pubi'
AS BEGIN
SET NOCOUNT ON
    BEGIN TRY


        -- *** BEGIN BLL ***


        declare @DBName nvarchar(max) 
        select top 1 @DBName = TABLE_CATALOG from INFORMATION_SCHEMA.TABLES
        exec sp_replicationdboption @dbname = @DBName, @optname = N'merge publish', @value = N'true'

        -- Mergeveröffentlichung wird hinzugefügt
        declare @desc nvarchar(max) = N'Mergeveröffentlichung der ' + @dbname + '-Datenbank von Verleger ' + @@SERVERNAME
        exec sp_addmergepublication 
            @publication = @PublicationName, 
            @description = @desc , 
            @sync_mode = N'native', 
            @retention = 14, 
            @allow_push = N'true', 
            @allow_pull = N'true', 
            @allow_anonymous = N'true', 
            @enabled_for_internet = N'false', 
            @snapshot_in_defaultfolder = N'true', 
            @compress_snapshot = N'false', 
            @ftp_port = 21, 
            @ftp_subdirectory = N'ftp', 
            @ftp_login = N'anonymous', 
            @allow_subscription_copy = N'false', 
            @add_to_active_directory = N'false', 
            @dynamic_filters = N'false', 
            @conflict_retention = 14, 
            @keep_partition_changes = N'false', 
            @allow_synctoalternate = N'false', 
            @max_concurrent_merge = 0, 
            @max_concurrent_dynamic_snapshots = 0, 
            @use_partition_groups = null, 
            @publication_compatibility_level = N'100RTM', 
            @replicate_ddl = 1, 
            @allow_subscriber_initiated_snapshot = N'false', 
            @allow_web_synchronization = N'false', 
            @allow_partition_realignment = N'true', 
            @retention_period_unit = N'days', 
            @conflict_logging = N'both', 
            @automatic_reinitialization_policy = 0


        exec sp_addpublication_snapshot 
            @publication = @PublicationName, 
            @frequency_type = 4, 
            @frequency_interval = 14, 
            @frequency_relative_interval = 1, 
            @frequency_recurrence_factor = 0, 
            @frequency_subday = 1, 
            @frequency_subday_interval = 5, 
            @active_start_time_of_day = 500, 
            @active_end_time_of_day = 235959, 
            @active_start_date = 0, 
            @active_end_date = 0, 
            @job_login = null, 
            @job_password = null, 
            @publisher_security_mode = 1

        declare @schema nvarchar(max), @table nvarchar(max), @uniquename nvarchar(max)
        declare cr cursor for
            select TABLE_SCHEMA, TABLE_NAME from INFORMATION_SCHEMA.TABLES 
            where TABLE_TYPE = 'BASE TABLE' and TABLE_NAME not like 'sys%' and TABLE_NAME not like 'ms%' and TABLE_NAME not like 'dtprop%'
            order by TABLE_NAME
        open cr
        WHILE 1=1 BEGIN
            FETCH cr INTO @schema, @table
            IF @@FETCH_STATUS <> 0 BREAK
            set @uniquename = @schema + @table

            print @schema + '.' + @table + ' (' + @uniquename + ')'
            exec sp_addmergearticle 
                @publication = @PublicationName, 
                @article = @uniquename, 
                @source_owner = @schema, 
                @source_object = @table, 
                @type = N'table', 
                @description = N'', 
                @creation_script = null, 
                @pre_creation_cmd = N'none', 
                @schema_option = 0x000000010C034FD1, 
                @identityrangemanagementoption = N'manual', 
                @destination_owner = @schema, 
                @force_reinit_subscription = 1, 
                @column_tracking = N'false', 
                @subset_filterclause = N'', 
                @vertical_partition = N'false', 
                @verify_resolver_signature = 1, 
                @allow_interactive_resolver = N'false', 
                @fast_multicol_updateproc = N'true', 
                @check_permissions = 0, 
                @subscriber_upload_options = 0, 
                @delete_tracking = N'true', 
                @compensate_for_errors = N'false', 
                @stream_blob_columns = N'false', 
                @partition_options = 0

        END 

        close cr
        deallocate cr





        -- *** END BLL ***

    END TRY
    BEGIN CATCH
        IF CURSOR_STATUS('global','cr') >= 0
        BEGIN 
            close cr
            deallocate cr
        END

        DECLARE @ErrMsg nvarchar(4000), @ErrSeverity INT, @ErrorState INT;
        SELECT @ErrMsg = ERROR_MESSAGE(),@ErrSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE()
        RAISERROR(@ErrMsg, @ErrSeverity, @ErrorState)


    END CATCH;

END
于 2021-07-27T19:13:52.427 に答える