別のデータベースと比較するために、いくつかのデータを含むデータベースをインポートしました。
ターゲットデータベースには照合Latin1_General_CI_AS
があり、ソースデータベースにはSQL_Latin1_General_CP1_CI_AS
があります。
SQL Server Management Studioを使用して、一般的にソースデータベースの照合をLatin1_General_CI_AS
に変更しました。ただし、内部のテーブルと列は古い照合順序のままです。
私は次を使用して列を変更できることを知っています:
ALTER TABLE [table]
ALTER COLUMN [column] VARCHAR(100) COLLATE Latin1_General_CI_AS
しかし、内部のすべてのテーブルとすべての列に対してこれを行う必要があります。
私が知る前に、すべてのテーブルとタイプvarchar
のすべての列を読み取り、テーブルと列カーソルループでそれらを変更するストアドプロシージャを書き始めます...
誰でも簡単な方法を知っていますか、またはプロシージャ内のすべてのテーブルを実行するスクリプトでこれを行う唯一の方法ですか?
適切な方法が見つからなかったため、それを行うスクリプトを作成しました。必要な人のためにここで共有しています。スクリプトはすべてのユーザーテーブルを実行し、列を収集します。列型が文字型の場合、指定された照合に変換しようとします。
これを機能させるには、列にインデックスと制約がない必要があります。
誰かがまだこれに対するより良い解決策を持っているなら、それを投稿してください!
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
だから、ここで私はもう一度、答えに満足していません。 JIRA 6.4.xをJIRA Software 7.xにアップグレードすることを任されましたが、データベースと列の照合に関する特定の問題に取り組みました。
SQL Serverでは、プライマリキー、外部キー、またはインデックスなどの制約を削除しないと、上記の回答として提供されたスクリプトはまったく機能しません。ただし、これらのプロパティがない場合は変更されます。すべての制約を手動で削除して元に戻したくないので、これは本当に問題です。その操作はおそらくエラーで終わる可能性があります。一方、変更を自動化するスクリプトを作成するには、時間がかかる場合があります。
そこで、SQL Management Studioを使用するだけで移行を行う方法を見つけました。手順は次のとおりです。
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
完了したら、JIRAを再起動し、データベースの照合が正常に完了しました。多くの人に役立つことを願っています!
長さの問題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
これを行うには、私のために働く簡単な解決策があります。
ただし、データベースにトリガーやプロシージャなどがある場合は、データやテーブルだけでなく、注意が必要です。
長さの問題nvarchar(最大値を含む)を修正し、テキストを追加し、NULL/NOT NULLを追加しました。
USE [put your database name here];
begin tran
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 @max_length_str nvarchar(100);
DECLARE @is_nullable bit;
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
ORDER BY [name]
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
, col.CHARACTER_MAXIMUM_LENGTH
, c.column_id
, c.is_nullable
FROM sys.columns c
JOIN sys.types t ON c.system_type_id = t.system_type_id
JOIN INFORMATION_SCHEMA.COLUMNS col on col.COLUMN_NAME = c.name and c.object_id = OBJECT_ID(col.TABLE_NAME)
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) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%')
AND c.collation_name <> @collate
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
set @max_length_str = @max_length
IF (@max_length = -1) SET @max_length_str = 'max'
IF (@max_length > 4000) SET @max_length_str = '4000'
BEGIN TRY
SET @sql =
CASE
WHEN @data_type like '%text%'
THEN 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + ' COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END
ELSE 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + '(' + @max_length_str + ') COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END
END
--PRINT @sql
EXEC sp_executesql @sql
END TRY
BEGIN CATCH
PRINT 'ERROR (' + @table + '): 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, @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
commit tran
GO
注意:次のような特定の照合使用条件を変更する必要がある場合:
WHERE c.object_id = OBJECT_ID(@table) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%')
AND c.collation_name = 'collation to change'
例えばNOT the:AND c.collation_name <> @collate
私の場合、いくつかの列の正しい/指定された照合があり、それらを変更したくありませんでした。
次のスクリプトは、(MAX)、IMAGEなどの最新のタイプとともにテーブルスキーマで動作します。この行の必要に応じて照合タイプを変更します(SET @collate = 'DATABASE_DEFAULT'; )
SQL SCRIPT HERE:
BEGIN
DECLARE @collate nvarchar(100);
declare @schema nvarchar(255);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length varchar(100);
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
SET @collate = 'DATABASE_DEFAULT';
DECLARE tbl_cursor CURSOR FOR SELECT (s.[name])schemaName, (o.[name])[tableName]
FROM sysobjects sy
INNER JOIN sys.objects o on o.name = sy.name
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE OBJECTPROPERTY(sy.id, N'IsUserTable') = 1
OPEN tbl_cursor FETCH NEXT FROM tbl_cursor INTO @schema,@table
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE tbl_cursor_changed 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 like OBJECT_ID(@schema+'.'+@table)
ORDER BY c.column_id
OPEN tbl_cursor_changed
FETCH NEXT FROM tbl_cursor_changed
INTO @row_id, @column_name, @data_type, @max_length, @column_id
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@max_length = -1) SET @max_length = 'MAX';
IF (@data_type LIKE '%char%')
BEGIN TRY
SET @sql = 'ALTER TABLE ' +@schema+'.'+ @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:'
PRINT @sql
END CATCH
FETCH NEXT FROM tbl_cursor_changed
INTO @row_id, @column_name, @data_type, @max_length, @column_id
END
CLOSE tbl_cursor_changed
DEALLOCATE tbl_cursor_changed
FETCH NEXT FROM tbl_cursor
INTO @schema, @table
END
CLOSE tbl_cursor
DEALLOCATE tbl_cursor
PRINT 'Collation For All Tables Done!'
END
PHPMyAdminを使用しているこのソリューションを探している人のために、「操作」タブの下部にオプションがあります(最初にデータベースをクリックします)。 2つのチェックボックス(最初のチェックボックスをオンにすると1つ表示されます):
基本的に投稿されたようなスクリプトを実行するようです。コンソールには、実行された最終コマンドが表示されます。
ALTER TABLE `DB_NAME`.`LAST_TABLE_IN_DB`DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci
私は常に純粋なSQLを好むので:
SELECT 'ALTER TABLE [' + l.schema_n + '].['
+ l.table_name + '] ALTER COLUMN ['
+ l.column_name + '] ' + l.data_type + '('
+ Cast(l.new_max_length AS NVARCHAR(100))
+ ') COLLATE ' + l.dest_collation_name + ';',
l.schema_n,
l.table_name,
l.column_name,
l.data_type,
l.max_length,
l.collation_name
FROM (SELECT Row_number()
OVER (
ORDER BY c.column_id) AS row_id,
Schema_name(o.schema_id) schema_n,
ta.NAME table_name,
c.NAME column_name,
t.NAME data_type,
c.max_length,
CASE
WHEN c.max_length = -1
OR ( c.max_length > 4000 ) THEN 4000
ELSE c.max_length
END new_max_length,
c.column_id,
c.collation_name,
'French_CI_AS' dest_collation_name
FROM sys.columns c
INNER JOIN sys.tables ta
ON c.object_id = ta.object_id
INNER JOIN sys.objects o
ON c.object_id = o.object_id
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 1 = 1
AND c.collation_name = 'SQL_Latin1_General_CP1_CI_AS'
--'French_CI_AS'-- ALTER DONE YET OLD VALUE :'SQL_Latin1_General_CP1_CI_AS'
) l
ORDER BY l.column_id;