原文:设置SQLServer数据库中某些表为只读的多种方法

翻译自:http://www.mssqltips.com/sqlservertip/2711/different-ways-to-make-a-table-read-only-in-a-sql-server-database/?utm_source=dailynewsletter&utm_medium=email&utm_content=headline&utm_campaign=2012614

在某些情况下需要把SQLServer的表设为只读,下面举出几种方法:

一般情况下会有几种情况需要你把数据库设为只读:

1.        Insert,Update,Delete 触发器

2.        Check 约束 和 Delete 触发器

3.        设置数据库为只读

4.        把表放到只读文件组中

5.        拒绝对象级别权限

6.        创建视图

在开始之前,先创建一个数据库及表作为示例:

create database MyDB
create table tblEvents
(
id int,
logEvent varchar(1000)
)
insert into tblEvents
values (1, 'Password Changed'), (2, 'User Dropped'), (3, 'Finance Data Changed')

nsert/Update/Delete触发器:

请注意这里使用的是INSTEADOF trigger,因为如果你使用了AFTER trigger,会在执行DELETE, UPDATE和INSERT语句时请求锁,会对写事务日志和回滚操作造成性能上的影响

CREATE TRIGGER trReadOnly_tblEvents ON tblEvents
INSTEAD OF INSERT,
UPDATE,
DELETE
AS
BEGIN
RAISERROR( 'tblEvents table is read only.', 16, 1 )
ROLLBACK TRANSACTION
END

当用户执行insert/update/delete时,将提示以下错误:

Msg 50000, Level 16, State 1, Procedure trReadOnly_tblEvents, Line 7
tblEvents table is read only.
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

使用 Check 约束和Delete 触发器:

现在先在表中添加一个check 约束“1=0”,意味着总是失败。它禁止你在任何行执行INSERT或者Delete操作。

首先,先禁用在上一步创建的触发器:disable trigger trReadOnly_tblEvents on tblevents
然后,添加约束:ALTER TABLE tblEvents WITH NOCHECK ADD CONSTRAINT chk_read_only_tblEvent CHECK( 1 = 0 )

执行以后,无论你执行任何一个INSERT/UPDATE语句,都将提示以下错误信息:

Msg 547, Level 16, State 0, Line 1

The UPDATE statement conflicted with the CHECKconstraint "chk_read_only_tblEvent". The conflict occurred indatabase "MyDB", table "dbo.tblEvents".

The statement has been terminated.

但是,该约束不会对DELETE操作造成影响,为此,需要再创建一个DDL触发器:

CREATE TRIGGER trReadOnlyDel_tblEvents ON tblEvents
INSTEAD OF
DELETE
AS
BEGIN
RAISERROR( 'tblEvents table is read only.', 16, 1 )
ROLLBACK TRANSACTION
END

设置数据库为只读:

你可以设置数据库为只读,这样就禁止对整个数据库的DDL/DML操作。可以使用以下语句:

USE [master]
GO
ALTER DATABASE [MyDB] SET READ_ONLY WITH NO_WAIT
GO

把表放到只读文件组:

可以在一个只读文件组中创建一个表:

USE [master]
GO
ALTER DATABASE [MyDB] ADD FILEGROUP [READ_ONLY_TBLS]
GO
ALTER DATABASE [MyDB] ADD FILE ( NAME = N'mydb_readonly_tables', FILENAME = N'C:\JSPACE\myDBReadOnly.ndf' , SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [READ_ONLY_TBLS]
GO
DROP table tblEvents
create table tblEvents
(
id int,
logEvent varchar(1000)
)
ON [READ_ONLY_TBLS]
ALTER DATABASE [MyDB] MODIFY FILEGROUP [READ_ONLY_TBLS] READONLY
任何对表的DML操作都会被拒绝,并返回以下错误信息:
Msg 652, Level 16, State 1, Line 1
The index "" for table "dbo.tblEvents" (RowsetId 72057594038845440) resides on a read-only filegroup ("READ_ONLY_TBLS"), which cannot be modified.

拒绝对象级别权限

可以通过DCL命令控制用户权限,但此步无法限制高级权限用户(如system admin,DatabaseOwner):

DENY INSERT, UPDATE, DELETE ON tblEvents TO Jugal
DENY INSERT, UPDATE, DELETE ON tblEvents TO Public

创建视图

为了替代直接访问表,可以使用视图:

create view vwtblEvents
as
select ID, Logevent from tblEvents
union all
select 0, '0' where 1=0

在这个视图中,使用了UNION,只有在你确保有对应数量的列时才使用。在这个例子中,表有两列,所以使用两个输出列。同时,你也应该确保数据类型也一致。

当一个用户尝试通过INSERT/UPDATE/DELETE操作数据时,将得到以下错误信息:

Msg 4406, Level 16, State 1, Line 1
Update or insert of view or function 'vwtblEvents1' failed because it contains a derived or constant field.
Msg 4426, Level 16, State 1, Line 1

View'vwtblEvents1' is not updatable because the definition contains a UNIONoperator.

最后一步:

确认是否有必要用这些步骤来设置表为只读。

如果一个表总是只读,那么你应该放到只读文件组中。

设置SQLServer数据库中某些表为只读的多种方法的更多相关文章

  1. PowerDesigner从SqlServer数据库中导入实体模型

    PowerDesigner从SqlServer数据库中导入实体模型 时间 2013-06-28 10:26:34 CSDN博客 原文  http://blog.csdn.net/sxycxwb/art ...

  2. 关于在Java中链接SQLServer数据库中失败的原因分析

    首先声明:笔者是Java的初学者,并且一值是走在自学的道路上,长久以来只有“度娘”相伴.(加入了各种Java学习群,基本没有热心帮人解决问题的.可以理解-_-!!!)大神级的人物就不必看拙文了,没有什 ...

  3. 批量解密SQLSERVER数据库中的各种对象的工具dbForge SQL Decryptor

    批量解密SQLSERVER数据库中的各种对象的工具dbForge SQL Decryptor2.1.11 之前写过一篇文章,使用redgate公司的SQL PROMPT工具,但是不太方便 SQLPRO ...

  4. 获取sqlserver数据库中所有库、表、字段名的方法

    获取sqlserver数据库中所有库.表.字段名的方法 2009年03月12日 星期四 下午 12:51 1.获取所有数据库名: SELECT Name FROM Master..SysDatabas ...

  5. 【转载】Sqlserver数据库中无自增Id的情况下使用ROW_NUMBER()函数进行数据分页

    在Sqlserver数据库中,如果查询表中含有自增长Id列,一般会采用select Top的方式来数据的分页操作.而实际上很多数据表设计的时候,不一定含有自增长Id列,那么数据库没有Id自增列的时候要 ...

  6. 设置SQLServer数据库内存

    需要设置SQLServer数据库的内存配置.登录数据库,这里使用的是SQLServer2008,右键点击最上方的服务器名,在弹出的菜单中,点击属性] 打开服务器属性窗口.默认显示的是第一项[常规]内容 ...

  7. Sqlserver数据库中的临时表详解

    临时表在Sqlserver数据库中,是非常重要的,下面就详细介绍SQL数据库中临时表的特点及其使用,仅供参考. 临时表与永久表相似,但临时表存储在tempdb中,当不再使用时会自动删除.临时表有两种类 ...

  8. SQLServer数据库中开启CDC导致事务日志空间被占满的原因

    SQLServer数据库中开启CDC导致事务日志空间被占满的原因 转载  2017-04-01   投稿:mrr    我要评论 这篇文章主要介绍了SQLServer数据库中开启CDC导致事务日志空间 ...

  9. Excel 数据导入至Sqlserver 数据库中 ltrim() 、rtrim() 、replace() 函数 依次空格无效问题

    今天导一些数据从Excel中至Sqlserver 数据库中,在做数据合并去重的时候发现,有两条数据一模一样,竟然没有进行合并: 最后发现有一条后面有个“空格”,正是因为这个“空格”让我抓狂许久,因为它 ...

随机推荐

  1. [IOS]UIWebView实现保存页面和读取服务器端json数据

    如何通过viewView保存访问过的页面?和如何获取并解析服务器端发送过来的json数据?通过一个简单的Demo来学习一下吧! 操作步骤: 1.创建SingleViewApplication应用,新建 ...

  2. Mysql加入用户时的错误问题

    比如:加入用户 insert into mysql.user(Host,User,Password) values("localhost","test",pas ...

  3. 外网SSH访问内网LINUX的N种方法

    外网SSH访问内网LINUX的N种方法 http://www.nat123.com/Pages_8_260.jsp 一,动态公网IP环境 1,环境描述: 路由器分配的是动态公网IP,且有路由管理权限, ...

  4. hash在Coreseek 中配置bigint

    304 $sphinxapi->SetSelect('id, domain_hash'); 304 $sphinxapi->SetConnectTimeout(3); 305 $sphin ...

  5. Java的wait(), notify()和notifyAll()使用心得(转)

    本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Obj ...

  6. C++0x新特性

    我是在一个帖子上摘抄的大神语录...感谢supermegaboy大神,给了详尽的解释 下文是一篇转载的Wikipedia的译文,从语言和库双方面概述了C++0x. 右值引用与转移语义 在标准C++语言 ...

  7. 前端构建工具gulp

    前端构建工具gulp使用   前端自动化流程工具,用来合并文件,压缩等. Gulp官网 http://gulpjs.com/ Gulp中文网 http://www.gulpjs.com.cn/ Gul ...

  8. android手机SD卡中的android_secure目录

    .android_secure 是官方app2sd的产物,删了之后装到sd卡中的软件就无法使用了.里面有非常多.asec的文件,都是装到SD卡上的软件,可是一般装到sd卡中的程序被卸载了.androi ...

  9. [2014 Regional]牡丹江 H Hierarchical Notation 做题记录

    主妇:老年人谁是炮灰牡丹江,我们的团队只是做同步大赛 他决定开爆震H什么时候,A 5min 1Y.I在该限制后,纠结了很久30min+ 1Y,神继续承担各种位置卡D在,hpp见B我认为这是非常熟悉的研 ...

  10. 给Ubuntu安装KDE桌面 [转]

    自ubuntu5.10发布以来,我非常难得的让她在我的硬盘上顽强生存了近3个月,仔细想想就连当年我第一个接触的红旗Linux也不过坚持了一个月,呵呵,又写了一段废话── 所 谓的“重回Kununtu” ...