原文:设置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 UITableView的Section Footer加入button

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 在处理UI ...

  2. The mell hall——坑爹

    The mell hall 题目描述 In HUST,there are always manystudents go to the mell hall at the same time as soo ...

  3. Python学习入门基础教程(learning Python)--3.3.2 Python的关系运算

    如果if的condition不用布尔表达式来做条件判断而采用关系表达式,实际上关系表达式运算的结果要么是True要么是False.下面我们先了解一些有关关系运算符的基础知识,如下表所示. 做个小程序测 ...

  4. BZOJ 1975 SDOI2010 魔法猪学院 A*k短路

    题目大意:给定一个值E 求起点到终点的最多条路径 使长度之和不超过E k短路的A*算法--每一个点有一个估价函数=g[x]+h[x] 当中g[x]是从源点出发已经走了的长度 h[x]是从这个点到汇点的 ...

  5. Gitblit配置

    Gitblit的安装配置及访问-windows (2013-09-11 11:52:31) 转载▼   分类: android基础 Git 是现在很流行的分布式版本控制工具,github更是人人皆知. ...

  6. AndroidUI的组成部分GridView

    java 代码例如以下(简单的知识点我会以凝视的形式解说): package com.gc.gridviewdemo; /** * @author Android将军 */ /** * 知识点解说: ...

  7. Linux Kernel(Android) 加密算法汇总(四)-应用程序调用OpenSSL加密演算法

    Linux Kernel(Android) 加密算法总结(三)-应用程序调用内核加密算法接口 讲到了怎样调用内核中的接口的方法. 本节主要是介绍怎样Android C/C++应用程序调用Openssl ...

  8. 关闭 sqlserver提示信息

  9. [Windows Phone] 以多国语言做为开发前提 (1)

    原文:[Windows Phone] 以多国语言做为开发前提 (1) ? 前言 在先前 TechDays 2013 的课程 [开发 Windows Phone 商务应用程式就是这麽快] 中,其中一个部 ...

  10. 使用邮件发送执行时间久的SQL语句

    ALTER proc [dbo].[usp_EmailLongRunningSQL] as begin declare@LongRunningQueries AS TABLE ( lrqId int ...