最近、ストアドプロシージャの実行中に次のエラーが発生し始めました。
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つ目は、サーバーの照合順序が変更されたことです。 システムの再構築 データベースが必要なため、これはveryとは考えられません。複数の管理者が無秩序な方法で作業を行う非常に動的な環境がない限り、これについてはこれ以上検討しません。
前半:データベースが別のインスタンスに移動された可能性はありますか?クライアント側のエイリアスを使用している場合、変更は透過的です。
2つ目は、データベースの照合順序が変更されたことです。これは非常に簡単です。必要なのは alter database
コマンド だけです。したがって、データベースの現在の照合と予期される照合を確認してください。それらは一致しますか?
3つ目は、ストアドプロシージャ自体が変更または名前変更されていることです。以前は明示的な照合指定があったかもしれませんが、それは削除されました。バージョン管理にsprocがありますか?
ストアドプロシージャの最終更新日を確認するには、sys.procedures
をクエリします。
SELECT create_date, modify_date, name
FROM sys.procedures;
私の知る限り、監査なしでは、事後のデータベース変更を把握することは困難です。ある種のCIシステムを使用している場合は、データベースまたはsprocsが最近再デプロイされたかどうかを再確認してください。
他のサーバー管理者や開発者ともチャットする価値はあります。
インスタンスレベルの照合順序が変更された可能性はほとんどありません。これは完全な停止を必要とし、誰かが気づくものです。
また、データベースレベルの照合順序が変更された可能性は非常に低いですが、COLLATE DATABASE_DEFAULT
ステートメントで見つかったCREATE table #temp
が次のように追加されたと仮定すると、その照合順序はこの操作に影響しないため、無関係ですこのエラーの修正。私はあなたの声明からこれを仮定します:
オンラインで確認したところ、...データベースの正しい照合順序で#Tempテーブルを作成することで問題を解決できることがわかりました。
(COLLATE DATABASE_DEFAULT
を追加する前に)この操作に影響するものは次のとおりです。
tempdb
の照合順序。これはshouldがインスタンスレベルの照合順序と同じであり、かつ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';