web-dev-qa-db-ja.com

「SQL_Latin1_General_CP1_CI_AS」と「Latin1_General_CI_AI」の間の照合の競合を解決できません

最近、ストアドプロシージャの実行中に次のエラーが発生し始めました。

 System.Data.SqlClient.SqlException(0x80131904):**「SQL_Latin1_General_CP1_CI_AS」と「Latin1_General_CI_AI」の間の照合の競合は操作と等しい**で解決できません。
 EXECUTE後のトランザクションカウントは、 BEGINステートメントとCOMMITステートメントの数が一致しません。以前のカウント= 0、現在のカウント= 1。
 at System.Data.SqlClient.SqlConnection.OnError(SqlException exception、Boolean breakConnection、Action`1 wrapCloseInAction)
 at System.Data.SqlClient.TdsParser .ThrowExceptionAndWarning(TdsParserStateObject stateObj、Boolean callerHasConnectionLock、Boolean asyncClose)
 at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopyHandlerSimpleResultSet) ] System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
でSystem.Data.SqlClient.SqlDataReader.get_MetaData()
 at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds、RunBehavior runBehavior、String resetOptionsString)
 at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Boolean async、Int32 timeout、Task&task、B oolean asyncWrite、SqlDataReader ds)
 at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String method、TaskCompletionSource`1 completion、Int32 timeout、Task&task、Boolean asyncWrite)
 at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String method)
 at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior、String method)
 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
 at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
 at System。 Data.Common.DbDataAdapter.FillInternal 

オンラインでチェックしてストアドプロシージャを観察したところ、ストアドプロシージャの開発者が#Tempテーブルを作成しており、データベースの正しい照合順序で#Tempテーブルを作成することで問題を解決できることがわかりました。

ストアドプロシージャが以前に適切に機能していて、この種のエラーを初めて受け取ったときに、この照合がどのように変更されたかを知りたいです。サーバーのWindows /セキュリティパッチの更新を継続的に取得しています。これらの更新により、データベースの照合プロパティが変更される可能性はありますか?

CREATE table  #temp( Code varchar(5) COLLATE DATABASE_DEFAULT null, Amount decimal(11,2) null )
INSERT into #temp select PT.Code,(PT.Percentage/100*(@PAmount+@ICharge+@FCharges+(select CC from @temp where [IN] = @MyVar))) from PTax PT inner join tax T on PT.Code=T.Code where Code = @strCode and PId=@PId AND T.Flag =@CFlag
INSERT INTO #temp SELECT T.Code,0 from Tax T where Flag =@CFlag AND T.Code not in (select Code from #temp)  
drop table #tempTaxes

最初のクエリに対する@Solomon Rutzky出力:

0   <Instance>      SQL_Latin1_General_CP1_CI_AS
1   master          SQL_Latin1_General_CP1_CI_AS
2   tempdb          SQL_Latin1_General_CP1_CI_AS
3   model           SQL_Latin1_General_CP1_CI_AS
4   msdb            SQL_Latin1_General_CP1_CI_AS
6   CustomerDB      Latin1_General_CI_AI

2番目のクエリ出力:

Latin1_General_CI_AI

3番目のクエリ出力:

Tax 2017-09-15 01:46:39.217 2017-09-15 01:46:39.217

どんな提案も大歓迎です。

1
Deepak Semwal

可能性について見てみましょう。 1つ目は、サーバーの照合順序が変更されたことです。 システムの再構築 データベースが必要なため、これはveryとは考えられません。複数の管理者が無秩序な方法で作業を行う非常に動的な環境がない限り、これについてはこれ以上検討しません。

前半:データベースが別のインスタンスに移動された可能性はありますか?クライアント側のエイリアスを使用している場合、変更は透過的です。

2つ目は、データベースの照合順序が変更されたことです。これは非常に簡単です。必要なのは alter databaseコマンド だけです。したがって、データベースの現在の照合と予期される照合を確認してください。それらは一致しますか?

3つ目は、ストアドプロシージャ自体が変更または名前変更されていることです。以前は明示的な照合指定があったかもしれませんが、それは削除されました。バージョン管理にsprocがありますか?

ストアドプロシージャの最終更新日を確認するには、sys.proceduresをクエリします。

SELECT create_date, modify_date, name
FROM sys.procedures;

私の知る限り、監査なしでは、事後のデータベース変更を把握することは困難です。ある種のCIシステムを使用している場合は、データベースまたはsprocsが最近再デプロイされたかどうかを再確認してください。

他のサーバー管理者や開発者ともチャットする価値はあります。

1
vonPryz

インスタンスレベルの照合順序が変更された可能性はほとんどありません。これは完全な停止を必要とし、誰かが気づくものです。

また、データベースレベルの照合順序が変更された可能性は非常に低いですが、COLLATE DATABASE_DEFAULTステートメントで見つかったCREATE table #tempが次のように追加されたと仮定すると、その照合順序はこの操作に影響しないため、無関係ですこのエラーの修正。私はあなたの声明からこれを仮定します:

オンラインで確認したところ、...データベースの正しい照合順序で#Tempテーブルを作成することで問題を解決できることがわかりました。

COLLATE DATABASE_DEFAULTを追加する前に)この操作に影響するものは次のとおりです。

  1. tempdbの照合順序。これはshouldがインスタンスレベルの照合順序と同じであり、かつ
  2. 一時テーブルの文字列列と比較される文字列列の照合順序:Tax.Code

これは、エラーがここで発生しているためです。

AND T.Code not in (select Code from #temp)

私の推測では、ストアドプロシージャが最近変更されていない場合(つまり、最初にCOLLATE DATABASE_DEFAULTが存在し、削除された場合)、CodeテーブルのTax列が更新された可能性があります。 NULL/NOT NULLを設定し、COLLATEキーワードをnotに指定した場合、andその列の元の照合順序がtempdbの照合順序と一致しました。あなたがこのようなものを実行するならば、私はこれを推測しています:

ALTER TABLE [Tax] ALTER COLUMN [Code] VARCHAR(10) NOT NULL;

次に、その列の照合順序が異なる場合は、データベースのデフォルトの照合順序に変更されます。

したがって、これを絞り込むために、次の3つのクエリの結果で質問を更新してください(これらを実行するときは、Taxテーブルを含むデータベースにいる必要があります)。

SELECT sd.[database_id], sd.[name], sd.[collation_name]
FROM   sys.databases sd
WHERE  sd.[database_id] IN (1, 2, 3, 4, DB_ID())
UNION ALL
SELECT 0 AS [database_id], '<Instance>' AS [name], SERVERPROPERTY('collation')
ORDER BY [database_id];

そして:

SELECT col.[collation_name]
FROM   sys.columns col
WHERE  col.[object_id] = OBJECT_ID(N'Tax')
AND    col.[name] = N'Code';

そして:

SELECT tab.[name], tab.[create_date], tab.[modify_date]
FROM   sys.tables tab
WHERE  tab.[name] = N'Tax';
1
Solomon Rutzky