目前我有一个带有“控制”列的表。该表通常包含两组数据,即活动集和旧集。更新数据时,表将包含活动集和新集。更新数据后,控制变量将被切换,新的集合将成为活动集,之前的活动集将成为旧集。每天一次,删除旧集并创建新集。此操作由几个中间步骤组成,这些步骤通常需要花费几个小时。问题是当创建新数据集时,活动集上的选择将超时。我已经添加了(nolock)这些选择,但这似乎没有帮助。
为了解决这个问题,我现在的计划是让两张表具有相同的定义。活动集将位于一个表中,旧/新集将位于另一个表中。我想做的是有一个视图,它将根据控制值从一个表或另一个表中选择数据。
我的控件是一个包含Id列和进度列的表。选择进入表格基本上是:
SELECT d.* FROM MyData d
JOIN ControlTable c ON c.ID = d.Control
WHERE c.Progress = 1000 -- 1000 is active
如何设置视图以根据控件查看一个或另一个表?我希望我可以将MyData从表格更改为视图,这样我的大部分代码都不会受到影响。
答案 0 :(得分:2)
创建同义词。
CREATE SYNONYM dbo.MyData FOR dbo.MyActiveData;
然后,当您进行维护或切换或有什么时候:
DROP SYNONYM dbo.MyData;
CREATE SYNONYM dbo.MyData FOR dbo.MyPassiveData;
现在您的视图可以简单地引用dbo.MyData
,但实际上会有条件地重定向到一个或另一个表。请注意,如果行数/数据在几天之间波动很大,那么这并不是真正的优化器。
答案 1 :(得分: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
答案 2 :(得分:0)
感谢那些回答的人。
我没有发现任何一个答案非常令人满意,所以我一直在调查一些选项。我想出的内容似乎很合理,不过我希望看到它的评论。
首先,我添加了一个列,以包含要用于Control表的表。接下来,我为两组数据设置了一个视图(假设有两个表: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的初步答案非常相似。我验证了当非活动数据集存在锁定时查询将起作用。