在 SQL Server 中将记录的状态设置为 false 之前检查记录的子记录
Posted
技术标签:
【中文标题】在 SQL Server 中将记录的状态设置为 false 之前检查记录的子记录【英文标题】:Check child records of a record before making status of it as false in SQL Server 【发布时间】:2018-08-17 14:17:41 【问题描述】:我的 SQL Server 数据库中有一个包含一些关系表的应用程序。
在应用程序中,每当用户删除和记录时,我从不将其从数据库中删除,而是将“状态”(表格列)设为“假”。
例如:用户将从tblAccounts
中删除一条记录,该记录有一个“状态”列,可以是真/假。删除操作记录时设置为 false。
现在的问题是此帐户可能会在其他交易中被引用。如果在其他表中使用,则不应允许用户删除(使其为 false)。
如果我允许用户从表中物理删除记录,它会抛出外键错误,但在这种情况下(使其为假)我如何检查子行而不删除并提示用户。
我可以通过对每个表的选择查询来做到这一点,但这会降低我的应用程序的速度。
还有其他方法/想法可以实现吗?
【问题讨论】:
我不太清楚你想要什么。更重要的是,您是否在使用此设置时遇到了问题,如果有,它们究竟是什么问题,或者您只是在猜测潜在的问题。 这个答案解释了一个调用 UDF 的检查约束,这可能是一个可能的解决方案。 --> ***.com/questions/13000698/… 我建议使用状态查找表而不是 True/False 字符串。老实说,对于一种身份来说,真假是没有意义的。也许 IsDeleted 会是一个更好的名称,然后使用 bit 数据类型。但我离题了。您是在问如何在 sql server 或您的应用程序中执行此操作吗?可悲的是,这个问题不是很清楚。我们可能还需要查看一些表定义和示例数据。 spaghettidba.com/2015/04/24/… 如果你想像硬删除一样防止软删除,你可以扩展外键来引用ID, Status
,而不是仅仅引用ID
(这需要这两个上的唯一索引列)。因为外键将始终将account_Status
设置为1
(或True
,我假设这是BIT
,就像肖恩说的那样,应该真正命名为Deleted
并且它的含义颠倒了)你可以这样做具有常量0
值的持久计算列。通过这种方式,更新被阻止的方式与删除相同,但代价是为冗余数据占用了一些存储空间。
【参考方案1】:
我可以通过对每个表的选择查询来做到这一点,但这会变慢 我的申请。
还有其他方法/想法可以实现吗?
不,没有。您可以使用调用函数的 CHECK 约束或使用 TRIGGER 进行自动化,但在该代码中,必须执行针对其他表的 SELECT 语句。没有办法解决。
【讨论】:
【参考方案2】:您可以使用外键来执行此操作,这里的技巧是在 tblAccounts 中将两个列(AccountID 和 Status)设为主要列。然后在事务表中,您创建一个外键(AccountID 和 Status),并在 UPDATE/Delete 时使用级联。这意味着,如果您从 tblAccounts 更改/删除帐户 ID 或其状态,这些更改也将应用于所有外键。
这是一个例子:
CREATE TABLE tblAccounts(
ID INT,
AccountID INT NOT NULL,
[Status] BIT NOT NULL
)
ALTER TABLE tblAccounts
ADD PRIMARY KEY (AccountID, [Status])
CREATE TABLE tblTransactions(
[ID] INT,
[TransID] INT NOT NULL PRIMARY KEY,
[AcctID] INT NOT NULL,
[Status] BIT NOT NULL
)
ALTER TABLE tblTransactions
ADD FOREIGN KEY (AcctID,[Status]) REFERENCES tblAccounts(AccountID, [Status])
ON UPDATE CASCADE
ON DELETE CASCADE
INSERT INTO tblAccounts (ID, AccountID, [Status])
VALUES
(1,1000,1),
(2,1100,1),
(3,1200,1),
(4,1300,1)
INSERT INTO tblTransactions(ID, TransID, AcctID,[Status])
VALUES
(1,5000,1000,1),
(2,3258,1300,1),
(3,5852,1000,1),
(4,9631,1100,1),
(5,1870,1200,1)
tblAccounts
| ID | AccountID | Status |
|----|-----------|--------|
| 1 | 1000 | true |
| 2 | 1100 | true |
| 3 | 1200 | true |
| 4 | 1300 | true |
tblTransactions
| ID | TransID | AcctID | Status |
|----|---------|--------|--------|
| 1 | 5000 | 1000 | true |
| 2 | 3258 | 1300 | true |
| 3 | 5852 | 1000 | true |
| 4 | 9631 | 1100 | true |
| 5 | 1870 | 1200 | true |
让我们将AccountID 1100的状态改为false
UPDATE tblAccounts
SET
[Status] = 0
WHERE
AccountID = 1100
检查 tblAccount
| ID | AccountID | Status |
|----|-----------|--------|
| 1 | 1000 | true |
| 2 | 1100 | false|
| 3 | 1200 | true |
| 4 | 1300 | true |
检查 tblTransactions
| ID | TransID | AcctID | Status |
|----|---------|--------|--------|
| 1 | 5000 | 1000 | true |
| 2 | 3258 | 1300 | true |
| 3 | 5852 | 1000 | true |
| 4 | 9631 | 1100 | false|
| 5 | 1870 | 1200 | true |
【讨论】:
感谢您的努力和回答,但不应继续更新 tblaccounts。外键的其他选项可以解决问题吗? @user10239717 外键与其父键(主键)相关。对父级的任何更改也会影响其子级。因此,如果不对主键(即 tblaccount 上的状态)进行更改,它将无法工作。您可以使用相同的方法,但使用不同的列(也许是新的?)以上是关于在 SQL Server 中将记录的状态设置为 false 之前检查记录的子记录的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Server Management Studio 中将列值设置为 NULL?