Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL:;“写保护”;可能有一行数据吗?_Sql_Sql Server_Sql Server 2005_Tsql - Fatal编程技术网

SQL:;“写保护”;可能有一行数据吗?

SQL:;“写保护”;可能有一行数据吗?,sql,sql-server,sql-server-2005,tsql,Sql,Sql Server,Sql Server 2005,Tsql,这可能是一个愚蠢的问题,但我可以在不设置用户权限的情况下保护SQL Server数据库中的一行数据不被删除或更新吗 这是一个默认的数据行,可以引用它的默认值 谢谢如果该行被更新或删除,您可能会触发引发错误的触发器。假设您的MyTable是主表 将第一行放入新表MyTableReadOnly中,将该表移动到它自己的文件组,并使该文件组为只读 从MyTable中删除第一行 现在创建一个 SELECT Columns From MyTableNew UNION SELECT Columns From

这可能是一个愚蠢的问题,但我可以在不设置用户权限的情况下保护SQL Server数据库中的一行数据不被删除或更新吗

这是一个默认的数据行,可以引用它的默认值


谢谢

如果该行被更新或删除,您可能会触发引发错误的触发器。

假设您的MyTable是主表

将第一行放入新表MyTableReadOnly中,将该表移动到它自己的文件组,并使该文件组为只读

从MyTable中删除第一行

现在创建一个

SELECT Columns From MyTableNew
UNION
SELECT Columns From MyTable
通过视图访问所有内容。如果要从视图中更新或删除,可以在MyTable上执行此操作,并忽略MyTableNew的任何内容。如果要使用视图,可以使用
而不是
触发器。

  • 创建第二个表,该表中的行具有与要保护的行相同的唯一ID

  • 请允许我按您的意愿打开第二张桌子

  • 在第一个表上添加触发器,如果第二个表中存在匹配行,则该触发器将删除/更新两个表

这样,除非在第二个表上有perm,否则将无法修改“链接”行,因为触发器将由于第二个表上的权限冲突而终止


注意:此方法与其他主要方法(使用视图)的对比在于,与视图方法不同,它允许轻松维护“固定”行集,并避免了通常与视图相关的各种性能问题。

我曾经使用过的一种可能方法在我的博客文章中描述:


“假设您需要执行以下业务规则:合同在您开始处理后不能更改(让我们假设特定业务在完美世界中运行)。您可以使用ROWVERSION列、持久化计算列和外键约束来实现此规则-

通过关系完整性来实现此操作-使用触发器,因为它们在以后维护时总是非常麻烦(它们有自己的位置,只是不在这里)。关系完整性可以满足您的所有需要

使用关系完整性可能非常简单,但您需要做的事情有点违反直觉,因此很容易被忽略

用一个数字主键创建主表tblMain。为了简单起见,我用一个包含一列intID的表测试了它,并用值0、1和2填充了它

接下来创建第二个表tblGuard,它具有类似的数字主键

现在是反向逻辑位。在引用tblMain表的tblGuard表上创建一个外键

ALTER TABLE [dbo].[tblGuard] ADD 
    CONSTRAINT [FK_tblGuard_tblMain] FOREIGN KEY 
    (
        [intID]
    ) REFERENCES [dbo].[tblMain] (
        [intID]
    )
该约束将确保不能从tblMain表中删除intID值为1的行,因为tblGuard表引用完整性要求tblMain中存在值1。这适用于删除和截断。

我说的是“以编程方式”这样做。
例如,让id为1的行始终为默认行,然后添加到所有更新或删除查询“WHERE id!=1“或使用编写逻辑所用的任何语言(PHP、C、VB等)进行等效操作

您为什么不想设置用户权限?答案可能不太好,但它是一个只有一个管理员用户的数据库。这不会检查perms Automatically在执行truncate table时忽略触发器。您不需要单独的权限级别来截断表而不是删除所有行吗?如果是这样,他可以单独设置权限oof限制了除admin之外的所有用户(这是应该的)。正如我所想的。在快速谷歌搜索之后,MSDN sez:“所需的最低权限是更改表名。TRUNCATE TABLE权限默认为表所有者、sysadmin固定服务器角色的成员以及db_所有者和db_ddladmin固定数据库角色,并且不可转移。“不,你可以通过关系完整性来做到这一点。除非你真的需要触发器,否则一定要避免触发器。请注意:为了解决Simon Svensson对提及触发器的不同解决方案的担忧,表截断不是一个问题,因为它需要单独的PERM和行删除。这很好。它允许你对行集授予权限。你gh,针对每个不同的(行集、权限)配对,则需要另一个表。例如,如果两个用户具有行级权限,但不在同一组行上,则需要为每个用户提供单独的控制表。我是否误解了实现?是的,确实如此。但这是我所知道的唯一使用本机表级权限的方法。其他任何方法都需要ei存储在表中的权限(例如,让触发器根据包含映射到权限的行ID的表检查您的用户ID,如果可行,可能使用DB的用户组,如果不可行,则直接检查用户ID)。您不需要使用触发器,您可以使用非常类似的方法来实现这一点,但使用关系完整性-触发器在其位置上很好,但由于跟踪它们很难,因此如果可以,最好避免使用它们。请参阅我的回答。原始问题要求在不设置用户权限的情况下提供解决方案。对于他的情况,有点过分了(因为您需要所有行的RowVersion列,而不仅仅是他试图保护的第一行),但它会起作用!这种方法有两个问题:如果受限制行列表发生更改,您必须维护视图(例如TDD而不是数据)。并且您必须为每一组单独的PERM创建一个新视图(与peter指出的我自己的方法相同的缺点)。这只会阻止删除,不会保护您的行不受更新。要求是:“保护SQL Server数据库中的一行数据不被删除或更新”