包含的數據庫歸類錯誤
將數據庫更改為部分包含時,出現以下錯誤:
無法解決 EXCEPT 操作中“Latin1_General_CI_AS”和“Latin1_General_100_CI_AS_KS_WS_SC”之間的排序規則衝突。
在編譯 > 對象期間,過程“RSExecRole.DeleteExtensionModuleDDL”中遇到錯誤。數據庫“VeeamOne”的包含選項已更改,或者此對象存在於模型 db 中,並且使用者嘗試創建新的包含數據庫。ALTER DATABASE 語句失敗。無法更改數據庫“VeeamOne”的包含選項,因為在驗證 SQL 模組期間遇到編譯錯誤。請參閱以前的錯誤。ALTER DATABASE 語句失敗。(.Net SqlClient 數據提供者)
我認為這是報告的對象來自 SSRS。但是,我正在更改排序規則的數據庫是一個完全獨立的應用程序。
有人對如何解決這個問題有任何建議嗎?
==================================================== ======================= 好的,這是proc的程式碼,不知道它是怎麼回事導致它無法被包含
USE [VeeamOne] GO /****** Object: StoredProcedure [reporter].[DeleteExtensionModuleDDL] Script Date: 02/12/2015 12:06:19 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [reporter].[DeleteExtensionModuleDDL] @EMID int AS BEGIN SET NOCOUNT ON; declare @Debug bit; set @Debug = 0; declare @Emulate bit; set @Emulate = 0; declare @reportPackDestructorFunctionName nvarchar(max) exec @reportPackDestructorFunctionName = [reporter].GenerateExtensionModuleDestructorName @EMID if exists(select * from sys.objects where (object_id = OBJECT_ID(@reportPackDestructorFunctionName) and type in (N'P', N'PC'))) begin exec @reportPackDestructorFunctionName declare @objectsToDelete as table (Name nvarchar(2048), Type nvarchar(2048)) insert @objectsToDelete exec @reportPackDestructorFunctionName if @Debug = 1 begin select * from @objectsToDelete end declare @TablesToDelete as table(ObjectID int, Name varchar(max)) declare @FunctionsToDelete as Table(Name nvarchar(max)) declare @StoredProceduresToDelete as Table(Name nvarchar(max)) declare @AssembliesToDelete as Table(Name nvarchar(max)) declare @ViewsToDelete as Table(Name nvarchar(max)) insert into @TablesToDelete select object_id(Name), Name from @objectsToDelete where Type = 'Table' insert into @FunctionsToDelete select Name from @objectsToDelete where Type = 'Function' insert into @StoredProceduresToDelete select Name from @objectsToDelete where Type = 'Procedure' union select @reportPackDestructorFunctionName insert into @AssembliesToDelete select Name from @objectsToDelete where Type = 'Assembly' insert into @ViewsToDelete select Name from @objectsToDelete where Type = 'View' declare @DependencyTree as Table(ForeignKeyObjectID int, ForeignKeyObjectName nvarchar(max), ParentTableID int, ParentTableName nvarchar(max), ChildTableID int, ChildTableName nvarchar(max), Generation int) declare @Generation int; set @Generation = 0; insert into @DependencyTree select distinct(fk.object_id) as ForeignKeyObjectID, fk.name as ForeignKeyObjectName, fk.referenced_object_id as ParentTableID, parent.name as ParentTableName, fk.parent_object_id as ChildTableID, child.name as ChildTableName, @Generation from sys.foreign_keys as fk inner join sys.objects as parent on fk.referenced_object_id = parent.object_id inner join sys.objects as child on fk.parent_object_id = child.object_id where fk.referenced_object_id in (select ObjectID from @TablesToDelete) while @@ROWCOUNT > 0 begin set @Generation = @Generation + 1 insert into @DependencyTree select fk.object_id as ForeignKeyObjectID, fk.name as ForeignKeyObjectName, fk.referenced_object_id as ParentTableID, parent.name as ParentTableName, fk.parent_object_id as ChildTableID, child.name as ChildTableName, @Generation from @DependencyTree dt inner join sys.foreign_keys as fk on fk.referenced_object_id = dt.ChildTableID inner join sys.objects as parent on fk.referenced_object_id = parent.object_id inner join sys.objects as child on fk.parent_object_id = child.object_id except select ForeignKeyObjectID, ForeignKeyObjectName, ParentTableID, ParentTableName, ChildTableID, ChildTableName, @Generation from @DependencyTree end declare @clearScript as table(ID int primary key identity (0,1), ScriptText nvarchar(max)) insert into @clearScript select 'alter table [reporter].[' + ChildTableName + '] drop constraint [' + ForeignKeyObjectName + ']' from @DependencyTree where ParentTableName in (select Name from @TablesToDelete) insert into @clearScript select 'drop table [reporter].[' + Name + ']' from @TablesToDelete insert into @clearScript select 'drop function [reporter].[' + Name + ']' from @FunctionsToDelete insert into @clearScript select 'drop procedure [reporter].[' + Name + ']' from @StoredProceduresToDelete insert into @clearScript select 'drop assembly [reporter].[' + Name + ']' from @AssembliesToDelete insert into @clearScript select 'drop view [reporter].[' + Name + ']' from @ViewsToDelete if @Debug = 1 begin select * from @clearScript end declare @str nvarchar(max) declare @ID int; set @ID = 0; declare @MaxID int select @MaxID = MAX(ID) from @clearScript print '' while @ID <= @MaxID begin select @str = ScriptText from @clearScript where ID = @ID if @Emulate = 1 print(@str) else exec sp_executesql @statement = @str set @ID = @ID + 1 end end END
您看到的問題是系統視圖中元數據的排序 -
sys.foreign_keys
和sys.objects
- 與表變數之間的衝突@DependencyTree
。正如@RLF 的回答中所指出的,當將數據庫更改為“包含”時,數據庫元數據的排序規則會從 DATABASE_DEFAULT(在您的情況下
Latin1_General_CI_AS
)更改為 CATALOG_DEFAULT(始終)。Latin1_General_100_CI_AS_WS_KS_SC
這會影響name
此查詢中返回的欄位:SELECT fk.object_id AS [ForeignKeyObjectID], fk.name AS [ForeignKeyObjectName], fk.referenced_object_id AS [ParentTableID], parent.name AS [ParentTableName], fk.parent_object_id AS ChildTableID, child.name AS [ChildTableName], @Generation FROM @DependencyTree dt INNER JOIN sys.foreign_keys fk ON fk.referenced_object_id = dt.ChildTableID INNER JOIN sys.objects parent ON fk.referenced_object_id = parent.[object_id] INNER JOIN sys.objects child ON fk.parent_object_id = child.[object_id] EXCEPT SELECT ForeignKeyObjectID, ForeignKeyObjectName, ParentTableID, ParentTableName, ChildTableID, ChildTableName, @Generation FROM @DependencyTree
、和欄位最初都被整理為,
fk.name
但隨後更改為當您更改數據庫以使其“包含”時。parent.name``child.name``Latin1_General_CI_AS``Latin1_General_100_CI_AS_WS_KS_SC
拋出錯誤是因為兩個部分的字元串欄位都
EXCEPT
需要匹配的排序規則。但另一部分EXCEPT
是使用定義為的表變數:DECLARE @DependencyTree as Table(ForeignKeyObjectID INT, ForeignKeyObjectName NVARCHAR(MAX), ParentTableID INT, ParentTableName NVARCHAR(MAX), ChildTableID INT, ChildTableName NVARCHAR(MAX), Generation INT)
沒有為這些
NVARCHAR(MAX)
欄位指定排序規則(從技術上講,它應該聲明為sysname
——對於那個總是小寫——因為那是源系統視圖的數據類型sys.objects
和sys.foreign_keys
)。雖然在Contained Database Collations Table MSDN 頁面中沒有提到它,但與臨時表不同,表變數從數據庫而不是從數據庫獲取其預設排序規則tempdb
(這就是為什麼您過去沒有看到此錯誤,因為您的tempdb
排序規則應該SQL_Latin1_General_CP1_CI_AS
是那是實例排序規則;如果此表是臨時表,您之前會收到此錯誤)。所以用於 , 和 欄位的ForeignKeyObjectName
排序ParentTableName
規則ChildTableName
是Latin1_General_CI_AS
並且在數據庫被“包含”時仍然是相同的排序規則。將該表變數聲明更改為以下內容應該可以解決此問題:
DECLARE @DependencyTree Table ( ForeignKeyObjectID INT, ForeignKeyObjectName sysname COLLATE CATALOG_DEFAULT, ParentTableID INT, ParentTableName sysname COLLATE CATALOG_DEFAULT, ChildTableID INT, ChildTableName sysname COLLATE CATALOG_DEFAULT, Generation INT );
使用
COLLATE CATALOG_DEFAULT
將在數據庫不包含以及將它們更改為包含時適用於數據庫,因為CATALOG_DEFAULT
解析為非包含數據庫中的數據庫預設值。說明這種行為的另一種方式是,由於數據庫元數據是在數據庫的任一狀態下進行整理CATALOG_DEFAULT
的,因此它將在數據庫的任一狀態下的表變數(和臨時表)中工作。