1

目前我有一个带有“控制”列的表。该表通常包含两组数据,活动集和旧集。更新数据时,表格将包含活动集和新集。一旦数据被更新,控制变量就被切换,新的集合变成活动的集合,之前的活动的集合变成旧的集合。每天一次,删除旧集并创建新集。此操作由几个中间步骤组成,通常需要几个小时。问题是当创建新的数据集时,活动集上的选择将超时。我已经在这些选择中添加了 with(nolock) ,但这似乎没有帮助。

为了克服这个问题,我现在的计划是有两个具有相同定义的表。活动集将在一个表中,旧/新集将在另一个表中。我想做的是有一个视图,它将根据控制值从一个表或另一个表中选择数据。

我的控件是一个带有 Id 列和进度列的表。选择到表中基本上是:

SELECT d.* FROM MyData d
JOIN ControlTable c ON c.ID = d.Control
WHERE c.Progress = 1000 -- 1000 is active

我将如何设置视图以根据控件查看一个表或另一个表?我希望我可以将 MyData 从表更改为视图,这样我的大部分代码都不会受到影响。

4

3 回答 3

2

创建同义词。

CREATE SYNONYM dbo.MyData FOR dbo.MyActiveData;

然后,当您进行维护或切换或您拥有什么时:

DROP SYNONYM dbo.MyData;
CREATE SYNONYM dbo.MyData FOR dbo.MyPassiveData;

现在您的视图可以简单地引用dbo.MyData,但实际上有条件地重定向到一个或另一个表。请注意,如果行数/数据在几天之间波动很大,这对优化器并不友好。

于 2013-10-07T19:48:40.963 回答
1

这行得通吗?

CREATE VIEW myView
AS
SELECT t.* FROM myTable1 t JOIN myControlTable c ON c.pk = 1 AND c.value = 1

UNION ALL

SELECT t.* FROM myTable2 t JOIN myControlTable c ON c.pk = 1 AND c.value = 2

您可能必须添加 WITH (NOLOCK) 作为“另一个” MyTable 在您处理它时可能会被锁定。

另一种解决方案是在两个表之间交换数据。这样,您将始终拥有一个“活动”表和一个“工作”表。=> 您的“报告”始终查看活动表 => 您的“处理”始终查看工作表

然后为此使用 ALTER TABLE SWITCH 命令。通常用于分区,但我相信它也可以在两个相同的表之间使用。

恕我直言,这将是一个更好的解决方案,因为您的报告和处理都不需要“动态”代码,但始终指向同一张表。

一些示例代码来说明我的意思:

-- cleanup
IF OBJECT_ID('myTable1') IS NOT NULL DROP TABLE myTable1 
IF OBJECT_ID('myTable2') IS NOT NULL DROP TABLE myTable2 
IF OBJECT_ID('swapTable') IS NOT NULL DROP TABLE swapTable

GO
-- creat 3 identical tables
CREATE TABLE myTable1 (pk       int IDENTITY(1, 1) NOT NULL 
                            CONSTRAINT pkTable1 PRIMARY KEY (pk),
                       value    int     NULL)

CREATE TABLE myTable2 (pk       int IDENTITY(1, 1) NOT NULL 
                            CONSTRAINT pkTable2 PRIMARY KEY (pk),
                       value    int     NULL)

CREATE TABLE swapTable (pk       int IDENTITY(1, 1) NOT NULL 
                            CONSTRAINT pkSwapTable PRIMARY KEY (pk),
                       value    int     NULL)

-- insert some data
INSERT myTable1 (value) VALUES (123)
INSERT myTable1 (value) VALUES (456)
INSERT myTable2 (value) VALUES (-1)


-- current situation
SELECT info = 'MyTable1', * FROM myTable1
SELECT info = 'MyTable2', * FROM myTable2

-- swap tables around
TRUNCATE TABLE swapTable
ALTER TABLE myTable1 SWITCH TO swapTable

TRUNCATE TABLE myTable1
ALTER TABLE myTable2 SWITCH TO myTable1

TRUNCATE TABLE myTable2
ALTER TABLE swapTable SWITCH TO myTable2 

GO
-- new situation
SELECT info = 'MyTable1', * FROM myTable1
SELECT info = 'MyTable2', * FROM myTable2
于 2013-10-07T20:29:51.780 回答
0

谢谢那些回答的人。

我没有找到任何一个非常令人满意的答案,所以我一直在研究一些选项。我想出的东西似乎是合理的,尽管我希望看到对此的评论。

首先,我添加了一个列来包含要用于控制表的表。接下来,我为这两组数据设置了一个视图(假设有两个表:MyData_1 和 MyData_2)

CREATE VIEW MyData AS
    SELECT d.* FROM MyData_1 d, Control c WHERE c.Progress = 1000 AND c.[Table] = 'MyData_1'
UNION ALL
    SELECT d.* FROM MyData_2 d, Control c WHERE c.Progress = 1000 AND c.[Table] = 'MyData_2'

我看到的缺点是,我需要更新所有从中选择活动集的代码

SELECT d.* FROM MyData d
JOIN ControlTable c ON c.ID = d.Control
WHERE c.Progress = 1000 -- 1000 is active

SELECT d.* FROM MyData d

这与@deroby 的初始答案非常相似。我验证了当非活动数据集上存在锁定时查询将起作用。

于 2013-10-08T00:14:51.817 回答