在SQL Server 2008 R2 Enterprise中创建分区视图
我正在扩展一些遗留软件,这些软件按公司将数据拆分为多个模式,例如CP1.ACCOUNTS、CP2.ACCOUNTS、CPN.ACCOUNTS。我试图使用分区创建这些表的可更新视图,但是我得到了典型的“由于未找到分区列而不可更新”错误。我试图划分的列是主键,据我所知,它不是任何不允许的东西 因此,对于这样的表定义:在SQL Server 2008 R2 Enterprise中创建分区视图,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我正在扩展一些遗留软件,这些软件按公司将数据拆分为多个模式,例如CP1.ACCOUNTS、CP2.ACCOUNTS、CPN.ACCOUNTS。我试图使用分区创建这些表的可更新视图,但是我得到了典型的“由于未找到分区列而不可更新”错误。我试图划分的列是主键,据我所知,它不是任何不允许的东西 因此,对于这样的表定义: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [CP1
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [CP1].[ACCOUNTS](
[ACCOUNTID] [char](10) NOT NULL,
[LASTNAME] [varchar](60) NOT NULL,
[FIRSTNAME] [varchar](35) NOT NULL,
[MIDDLE] [varchar](26) NULL,
[SUFFIX] [varchar](10) NULL,
[ADDRESS1] [varchar](55) NULL,
[ADDRESS2] [varchar](55) NULL,
[SOME_FLAG] [tinyint] NULL,
CONSTRAINT [ARM_CODE_KEY] PRIMARY KEY CLUSTERED
(
[CODE_] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [CP1].[ACCOUNTS] WITH CHECK ADD CONSTRAINT [CK__ACCOUNTS__CODE___4DD705FF] CHECK ((left([ACCOUNTID],(3))='CP1'))
GO
ALTER TABLE [CP1].[ACCOUNTS] CHECK CONSTRAINT [CK__ACCOUNTS__CODE___4DD705FF]
GO
ALTER TABLE [CP1].[ACCOUNTS] ADD DEFAULT ((0)) FOR [SOME_FLAG]
GO
其余的表完全按照上面的定义,遵循CP2、CP3、CPN模式,视图定义是简单的:
CREATE VIEW [ALL].[ACCOUNTS] AS
SELECT * FROM CP1.ACCOUNTS
UNION ALL
SELECT * FROM CP2.ACCOUNTS
--UNION ALL etc...
插入内容如下:
INSERT INTO [ALL].[ACCOUNTS]
([ACCOUNTID]
,[LASTNAME]
,[FIRSTNAME]
,[MIDDLE]
,[SUFFIX]
,[ADDRESS1]
,[ADDRESS2]
,[SOME_FLAG])
VALUES
('CP1XYZ0001',
'SMITH',
'JOHN',
'Q',
'',
'123 Fake St',
'Apt 2',
0,
GO
生成如下错误:
Msg 4436, level 16, State 12, Line 1
UNION ALL view 'ALL.ACCOUNTS' is not updatable because a partitioning column was not found.
我错过了一些简单的东西吗?我是不是在左边的字段中走得太远了?您需要一个约束来定义哪个列用作分区列。正如错误所示,您没有定义一个。如以下文件所述: 要在分区视图上执行更新,分区列必须 是基表主键的一部分。如果一个视图不是 可更新,您可以在 允许更新。您应该在触发器中设计错误处理,以 确保没有插入重复的行。例如 请参见设计而不是在视图上设计触发器,而不是在视图上设计触发器 触发器 换句话说,SQL Server需要能够确定哪个表得到更新 您可以修改表以包含公司名称列,然后将其用作主键的一部分。类似的方法可能会奏效:
create table . . .
CompanyName as 'CompanyA',
primary key (AccountId, CompanyName)
. . .
另一种方法是使用
而不是触发器,如文档中所建议的那样。如果有人遇到这种情况,您可以使用计算列进行分区,只需确保它是一个持久的计算列
在这种情况下,计算列应该是left([ACCOUNTID],(3)
,分区约束应该是='CP1'
。注意:在约束中使用left()
将导致它仍然扫描所有分区。检查约束只能使用以下运算符:介于和之间,或者,=,=。
此外,由于问题引用了企业版,因此使用分区表而不是分区视图可以获得更好的性能。您可以编辑问题并包含更新语句吗?感谢您的建议,@gordon linhoff。我添加了insert语句,以及收到的错误的确切文本。Since是一个现有的表,您可以在表定义末尾附近的ALTER table
语句中找到约束。特别是ALTER table[CP1].[ACCOUNTS]和CHECK ADD constraint[CK\u ACCOUNTS\uuuu code\uuuu 4DD705FF]检查((左([ACCOUNTID],(3))='CP1'))
不幸的是,无法使用附加列,因为无法更新旧软件以指定插入时的值,并且分区列不支持默认值。我猜SQL Server无法识别左侧(AccountId,3)
作为主键的一部分。请尝试添加计算列并在约束中使用它。不幸的是,计算列对于分区无效。我还查看了而不是触发器,发现这可能不适用于基于集合的操作。要插入的表可能会随着行的变化而变化。我没有注意到“我不确定计算列是否可用于分区。您可以在每个表上放置一个触发器,使用ACCOUNTID3
(定义为offACCOUNTID
)添加一个新列。然后您可以将其用于分区。”。