SQL Server

接触触发器

触发器是数据库服务器中发生事件时自动执行的特种存储过程。如果用户要通过数据操作语言 (DML) 事件编辑数据,则执行 DML 触发器。DML 事件是针对表或视图的 INSERT、UPDATE 或 DELETE 语句。

现在有一个这样的需求,想在插入新数据到 news 表时,先对 title 字段进行检查,要是有相同数据的就停止插入。

先创建一个触发器:checknews

CREATE TRIGGER checknews -- checknews 为触发器名称
ON news -- ON 后面是触发器所属表
AFTER INSERT -- 触发器类型
AS
begin
if exists(select 1 from inserted join news on inserted.title=news.title)
  ROLLBACK TRANSACTION
end

咋一看,没什么问题,其实达不到我们想要的效果;指定触发器类型有三个关键词,分别是:FOR, AFTER, INSTEAD OF

AFTER:它是先执行操作,再运行触发器的,像上面的触发器,是永远都无法往表添加记录的。

FOR:如果仅指定 FOR 关键字,则 AFTER 为默认值,经测试我觉得 AFTER 和 FOR 为同样的效果。

INSTEAD OF:它不执行其所定义的操作(INSERT,UPDATE,DELETE),也就是用户操作,而执行触发器本身!也就是说,尽管触发器被触发,但相应的操作并不执行,而运行的仅是触发器 SQL 语句本身。对于统一操作只能定义一个 INSTEAD OF 触发器!

明白以上的,改一下触发器:

CREATE TRIGGER checknews
ON news
AFTER INSERT
AS
begin
declare @count int
select @count = count(*) from inserted join news on inserted.title=news.title
if @count > 1
  ROLLBACK TRANSACTION -- 回滚
end

至此,需求就实现了,如果说一定要用 exists,怎么实现呢?那就用 INSTEAD OF 了。


CREATE TRIGGER checknews
ON news
INSTEAD OF INSERT
AS
begin
if not exists(select 1 from inserted join news on inserted.title=news.title)
  INSERT INTO news SELECT [title], [image] FROM inserted
end


刚接触触发器(我就是)的朋友可能会问 inserted 是什么?它是一个临时表,还有 deleted,均是用在触发器的,详细介绍请看:

http://tech.ccidnet.com/art/1106/20080310/1384913_1.html

清除 SQL Server 日志

当数据库日志满了会提示:数据库 '**' 的日志已满。请备份该数据库的事务日志以释放一些日志空间。

解决办法:

1. 清空日志
DUMP TRANSACTION 库名 WITH NO_LOG

2. 收缩数据库文件(如果不压缩,数据库的文件和日志文件是不会减小的)
a. 右键你要压缩的数据库 -> 任务 -> 收缩 -> 文件
b. 在“文件类型”选择“日志” -> 在“收缩操作”那选中“在释放未使用的空间前重新组织页”,这里会给出一个允许收缩到的最小 M 数,直接输入这个数即可 -> 确定
c. 再执行步骤 a,在“文件类型”选择“数据” -> 在“收缩操作”那选中“在释放未使用的空间前重新组织页”,这里会给出一个允许收缩到的最小 M 数,同样直接输入这个数即可 -> 确定

数据的收缩会慢一点,特别是几百 M 以上的,要耐心等待,别中途取消。

注:数据库版本:SQL Server 2005 企业版

[转]删除 master 库中不安全的扩展存储过程

use master
go

--它可以直接运行系统命令--------------------------------------------------
execute sp_dropextendedproc 'xp_cmdshell'
go

--对安全有威胁的OLE存储过程-----------------------------------------------
execute sp_dropextendedproc 'sp_OACreate'
go
execute sp_dropextendedproc 'sp_OADestroy'
go
execute sp_dropextendedproc 'sp_OAGetErrorInfo'
go
execute sp_dropextendedproc 'sp_OAGetProperty'
go
execute sp_dropextendedproc 'sp_OAMethod'
go
execute sp_dropextendedproc 'sp_OASetProperty'
go
execute sp_dropextendedproc 'sp_OAStop'
go

--访问注册表的存储过程----------------------------------------------------
execute sp_dropextendedproc 'Xp_regaddmultistring'
go
execute sp_dropextendedproc 'Xp_regdeletekey'
go
execute sp_dropextendedproc 'Xp_regdeletevalue'
go
execute sp_dropextendedproc 'Xp_regenumvalues'
go
execute sp_dropextendedproc 'Xp_regremovemultistring'
go
execute sp_dropextendedproc 'Xp_regwrite'
go

--以下这些存储过程也有一定的安全隐患---------------------------------------
execute sp_dropextendedproc 'sp_sdidebug'
go
execute sp_dropextendedproc 'xp_deletemail'
go
execute sp_dropextendedproc 'xp_dirtree'
go
execute sp_dropextendedproc 'xp_dropwebtask'
go
execute sp_dropextendedproc 'xp_enumerrorlogs'
go
execute sp_dropextendedproc 'xp_eventlog'
go
execute sp_dropextendedproc 'xp_sscanf'
go
execute sp_dropextendedproc 'xp_findnextmsg'
go
execute sp_dropextendedproc 'xp_fixeddrives'
go
execute sp_dropextendedproc 'xp_getfiledetails'
go
execute sp_dropextendedproc 'xp_logevent'
go
execute sp_dropextendedproc 'xp_subdirs'
go
execute sp_dropextendedproc 'xp_makewebtask'
go
execute sp_dropextendedproc 'xp_readmail'
go
execute sp_dropextendedproc 'xp_runwebtask'
go
execute sp_dropextendedproc 'xp_readerrorlog'
go
execute sp_dropextendedproc 'xp_sendmail'
go
execute sp_dropextendedproc 'xp_sprintf'
go
execute sp_dropextendedproc 'xp_servicecontrol'
go
execute sp_dropextendedproc 'xp_stopmail'
go
execute sp_dropextendedproc 'xp_startmail'
go
execute sp_dropextendedproc 'xp_unc_to_drive'
go

--############################################################
--访问注册表的存储过程中
--execute sp_dropextendedproc 'Xp_regread'
--go
--删除后在SQL Server代理的作业中无法看作业的属性
--关系DLL文件为xpstar.dll
--############################################################

--execute sp_dropextendedproc 'xp_grantlogin'
--go
--无法 将 DROP PROCEDURE 用于 'xp_grantlogin',因为 'xp_grantlogin' 是 过程。请使用 DROP PROCEDURE。

--execute sp_dropextendedproc 'xp_logininfo'
--go
--无法 将 DROP PROCEDURE 用于 'xp_logininfo',因为 'xp_logininfo' 是 过程。请使用 DROP PROCEDURE。

--execute sp_dropextendedproc 'xp_revokelogin'
--go
--无法 将 DROP PROCEDURE 用于 'xp_revokelogin',因为 'xp_revokelogin' 是 过程。请使用 DROP PROCEDURE。

--############################################################
--execute sp_dropextendedproc 'xp_msver'
--go
--execute sp_dropextendedproc 'xp_loginconfig'
--go
--execute sp_dropextendedproc 'sp_addlogin'
--go
--execute sp_dropextendedproc 'sp_password'
--go
--execute sp_dropextendedproc 'sp_addsrvrolemember'
--go
--############################################################
--恢复扩展存储过程
--sp_addextendedproc 'xp_cmdshell', 'xpLOG70.dll'
--sp_addextendedproc 'Xp_regread', 'xpstar.dll'

SQL Server 2005 分页功能

SELECT TOP 10 * FROM bbs_user ORDER BY jointime

SELECT * FROM (select *, ROW_NUMBER() Over(order by jointime) as rowNum from bbs_user) as bbs_user where rowNum between 3 and 6;

第二条语句是获取中间的第 3 4 5 6 条记录!