原文:深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数

概述

COLUMNS_UPDATED函数能够出现在INSERT或UPDATE触发器中AS关键字后的任何位置,用来指示表或视图中有哪些列已被插入或者更新。它通常和IF语句一起使用,从而可以根据不同的结果,促使触发器执行不同的操作。因此在DML触发器中,COLUMNS_UPDATED函数是一个非常重要且有用的函数。

不同于UPDATE函数,COLUMNS_UPDATED函数可以工作在多个列中,它使用字节中的位(Bit)标识列是否已被修改(也就是采用二进制的方式),而不是在参数中传递列名。我们都知道,1字节(BYTE)=8比特(Bit),因此仅仅使用COLUMNS_UPDATED函数,则只能够标识一个表或视图的前八列是否被修改。如果表的列多于八列,那么必须和SUBSTRING函数一起搭配使用,这将在后文中进行详细讨论。

对COLUMNS_UPDATED函数的原理分析

COLUMNS_UPDATED函数返回类型为varbinary,这是一种二进制类型,它可以表示一个或多个字节,用来映射相关联表的列。因此COLUMNS_UPDATED函数至8的列,越偏向右侧的字节,其所代表的列的序号也就越大。而列序号的排序是在创建表时,由列被定义的顺序所决定的。在每个字节的内部,越偏向左侧,列的序号越大,而左侧字节所代表的列的序号总小于右侧字节的。请允许我用一个简单的示例来阐述上述过程:

个列,分别为COL1、COL2、COL3直至COL24。那么COLUMNS_UPDATED函数就会返回3个字节,在最左侧的字节内由右向左表示COL1至COL8,中间的字节内由右向左表示COL9至COL16,最右侧的字节内由右向左表示COL17至COL24。

正如我之前所说,1字节中的8比特就可以表示一张表的前八列,如果某一为1,那么它所表示的列被标记为已更新。反之为0,那么就是未更新。如果多个列被更新,那么就会存在有多个位被设置为1的情况。例如00001010就表示第二列和第四列已经被更新。

 

使用COLUMNS_UPDATED函数测试前八列

对于位(Bit)要说的是,第一个称为Bit0(而不是Bit1),因此1个字节是由Bit0至Bit7共八个位所组成的。有几个列被更新,COLUMNS_UPDATED函数就会返回一个所对应的位设置为1的字节。如果我们要想知道第二列和第四列是否被更新,就应该构造出一个字节,并将Bit1和Bit3设置为1(00001010),然后需要将这个字节转换成十进制10,再和COLUMNS_UPDATED函数返回的字节进行按位逻辑与(&)操作,&运算的结果如果是10,就能够保证第二列和第四列已经同时被更新。再结合使用不同的比较运算符(<、>、=),处理各种各样的可能性,你就会真切体会到COLUMNS_UPDATED函数的功能是多么的强大了。好了,为了便于理解,请看一个完整的代码演示:

CREATE TRIGGER updDataTrigger

ON TriggerDemo

AFTER UPDATE AS

--测试第二列和第四列是否被同时更新

IF COLUMNS_UPDATED() & 10 =10

BEGIN

…………

END

--是否第二列或者第四列或者第二列和第四列同时被更新

ELSE IF COLUMNS_UPDATED() & 10 > 0 AND COLUMNS_UPDATED()&10<=10

BEGIN

…………

END

--测试第二列或者第四列是否已被更新

ELSE IF COLUMNS_UPDATED() & 10 <10 AND COLUMNS_UPDATED() & 10>0

BEGIN

…………

END

使用COLUMNS_UPDATED函数测试八个以上的列

一旦表拥有八个以上的列,COLUMNS_UPDATED函数将会返回多个字节。这时我们就需要借助SUBSTRING函数来截取一个特定的字节,它可以从COLUMNS_UPDATED函数返回的多个字节中任意截取一个我们所想要的。

还记得我们前面的那张虚拟表TriggerDemo吗?(就是拥有24个列的那个) 如果我们想测试它的第二列、第十列以及第二十四列是否已被更新,我们就需要使用SUBSTRING函数来截取到分别代表这些列的字节,再重复前面测试前八列方法的步骤。我们参见一下代码:

--测试第二列、第十列以及第二十四列是否同时被更新

IF(SUBSTRING(COLUMNS_UPDATED(),1,1)&2=2)

AND (SUBSTRING(COLUMNS_UPDATED(),2,1)&2=2)

AND(SUBSTRING(COLUMNS_UPDATED(),3,1)&128=128)

BEGIN

…………

END

总结

本文详细讲解了该如何使用COLUMNS_UPDATED函数,首先介绍了它的基本工作原理,然后对于测试前八列和八个以上的列这两种情况,详述了运用COLUMNS_UPDATED函数的两种不同方法。为了便于理解它的功能强大,还插入了相关的代码片段和引入了一个虚拟的表TriggerDemo。通过这种方式,我们就能够深刻体会到为什么它是UPDATE触发器必不可少的助手。最后祝愿大家编程愉快。

概述

COLUMNS_UPDATED函数能够出现在INSERT或UPDATE触发器中AS关键字后的任何位置,用来指示表或视图中有哪些列已被插入或者更新。它通常和IF语句一起使用,从而可以根据不同的结果,促使触发器执行不同的操作。因此在DML触发器中,COLUMNS_UPDATED函数是一个非常重要且有用的函数。

不同于UPDATE函数,COLUMNS_UPDATED函数可以工作在多个列中,它使用字节中的位(Bit)标识列是否已被修改(也就是采用二进制的方式),而不是在参数中传递列名。我们都知道,1字节(BYTE)=8比特(Bit),因此仅仅使用COLUMNS_UPDATED函数,则只能够标识一个表或视图的前八列是否被修改。如果表的列多于八列,那么必须和SUBSTRING函数一起搭配使用,这将在后文中进行详细讨论。

对COLUMNS_UPDATED函数的原理分析

COLUMNS_UPDATED函数返回类型为varbinary,这是一种二进制类型,它可以表示一个或多个字节,用来映射相关联表的列。因此COLUMNS_UPDATED函数返回一个或多个由左向右排序的字节,这取决于要验证更新的表是否拥有八个以上的列。最左侧字节表示列的序号为1至8的列,越偏向右侧的字节,其所代表的列的序号也就越大。而列序号的排序是在创建表时,由列被定义的顺序所决定的。在每个字节的内部,越偏向左侧,列的序号越大,而左侧字节所代表的列的序号总小于右侧字节的。请允许我用一个简单的示例来阐述上述过程:

我们假设有一张表TriggerDemo,它拥有24个列,分别为COL1、COL2、COL3直至COL24。那么COLUMNS_UPDATED函数就会返回3个字节,在最左侧的字节内由右向左表示COL1至COL8,中间的字节内由右向左表示COL9至COL16,最右侧的字节内由右向左表示COL17至COL24。

正如我之前所说,1字节中的8比特就可以表示一张表的前八列,如果某一为1,那么它所表示的列被标记为已更新。反之为0,那么就是未更新。如果多个列被更新,那么就会存在有多个位被设置为1的情况。例如00001010就表示第二列和第四列已经被更新。

 

使用COLUMNS_UPDATED函数测试前八列

对于位(Bit)要说的是,第一个称为Bit0(而不是Bit1),因此1个字节是由Bit0至Bit7共八个位所组成的。有几个列被更新,COLUMNS_UPDATED函数就会返回一个所对应的位设置为1的字节。如果我们要想知道第二列和第四列是否被更新,就应该构造出一个字节,并将Bit1和Bit3设置为1(00001010),然后需要将这个字节转换成十进制10,再和COLUMNS_UPDATED函数返回的字节进行按位逻辑与(&)操作,&运算的结果如果是10,就能够保证第二列和第四列已经同时被更新。再结合使用不同的比较运算符(<、>、=),处理各种各样的可能性,你就会真切体会到COLUMNS_UPDATED函数的功能是多么的强大了。好了,为了便于理解,请看一个完整的代码演示:

CREATE TRIGGER
updDataTrigger

ON TriggerDemo

AFTER UPDATE AS

测试第二列和第四列是否被同时更新

IF
COLUMNS_UPDATED() & 10 =10

BEGIN

…………

END

是否第二列或者第四列或者第二列和第四列同时被更新

ELSE IF COLUMNS_UPDATED()
& 10 > 0 AND COLUMNS_UPDATED()&10<=10

BEGIN

…………

END

测试第二列或者第四列是否已被更新

ELSE IF COLUMNS_UPDATED()
& 10 <10 AND COLUMNS_UPDATED() & 10>0

BEGIN

…………

END

使用COLUMNS_UPDATED函数测试八个以上的列

一旦表拥有八个以上的列,COLUMNS_UPDATED函数将会返回多个字节。这时我们就需要借助SUBSTRING函数来截取一个特定的字节,它可以从COLUMNS_UPDATED函数返回的多个字节中任意截取一个我们所想要的。

还记得我们前面的那张虚拟表TriggerDemo吗?(就是拥有24个列的那个) 如果我们想测试它的第二列、第十列以及第二十四列是否已被更新,我们就需要使用SUBSTRING函数来截取到分别代表这些列的字节,再重复前面测试前八列方法的步骤。我们参见一下代码:

测试第二列、第十列以及第二十四列是否同时被更新

IF(SUBSTRING(COLUMNS_UPDATED(),1,1)&2=2)

AND
(SUBSTRING(COLUMNS_UPDATED(),2,1)&2=2)

AND(SUBSTRING(COLUMNS_UPDATED(),3,1)&128=128)

BEGIN

…………

END

总结

本文详细讲解了该如何使用COLUMNS_UPDATED函数,首先介绍了它的基本工作原理,然后对于测试前八列和八个以上的列这两种情况,详述了运用COLUMNS_UPDATED函数的两种不同方法。为了便于理解它的功能强大,还插入了相关的代码片段和引入了一个虚拟的表TriggerDemo。通过这种方式,我们就能够深刻体会到为什么它是UPDATE触发器必不可少的助手。最后祝愿大家编程愉快。

深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数的更多相关文章

  1. sql server 2005中的分区函数用法(partition by 字段)

    分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系统中取出每个学科前3名的学生.这种查询在SQL Server 2005之前,写起来很繁琐,需要用到临时表关联查询才能取到.SQL Serve ...

  2. SQL Server 2005 中的分区表和索引

    SQL Server 2005 中的分区表和索引 SQL Server 2005          69(共 83)对本文的评价是有帮助 - 评价此主题   发布日期 : 3/24/2005 | 更新 ...

  3. SQL Server 2005中的分区表

    记录笔记: 转自 猪八戒学做网站 SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表? SQL Server 2005中的分区表(二):如何添加.查询.修改 ...

  4. SQL Server 2005中更改sa的用户名和密码

    修改数据库SA账号名称的代码如下:  代码如下: Alter LOGIN sa DISABLE Alter LOGIN sa WITH NAME = [systemAccount] "sys ...

  5. SQL Server 2005 中实现通用的异步触发器架构

    在SQL Server 2005中,通过新增的Service Broker可以实现异步触发器的处理功能.本文提供一种使用Service Broker实现的通用异步触发器方法. 在本方法中,通过Serv ...

  6. SQL SERVER 2005中同义词实例

    From : http://www.cnblogs.com/jackyrong/archive/2006/11/15/561287.html 在SQL SERVER 2005中,终于出现了同义词了,大 ...

  7. SQL Server 2005中的分区表(六):将已分区表转换成普通表(转)

    我的俄罗斯名叫作“不折腾不舒服斯基”,所以,不将分区表好好折腾一下,我就是不舒服. 在前面,我们介绍过怎么样直接创建一个分区表,也介绍过怎么将一个普通表转换成一个分区表.那么,这两种方式创建的表有什么 ...

  8. 浅析SQL Server 2005中的主动式通知机制

    一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...

  9. SQL Server 2005中的CHECKSUM功能

    原文:SQL Server 2005中的CHECKSUM功能 转自此处 页面 checksum 是SQL2005的新功能,提供了一种比残缺页检测强大的机制检测IO方面的损坏.以下是详细描述: 页面 C ...

随机推荐

  1. Android Thread.setDaemon设置说明

    Thread.setDaemon的用法,经过学习以后了解: 1. setDaemon需要在start方法调用之前使用 2. 线程划分为用户线程和后台(daemon)进程,setDaemon将线程设置为 ...

  2. spring mvc controller接收请求值及controller之间跳转及传值

    spring接收请求参数: 1,使用HttpServletRequest获取 @RequestMapping("/login.do") public String login(Ht ...

  3. [Ramda] Filter an Array Based on Multiple Predicates with Ramda's allPass Function

    In this lesson, we'll filter a list of objects based on multiple conditions and we'll use Ramda's al ...

  4. Oracle数据库sqlplus与plsqldev解决乱码

    (出现乱码 解决方法留存) 问题描述 : 在用eclipse使用jdbc插入中文数据的时,数据用plsqldev查询时,正常显示中文,但是用sqlplus查询时,为中文乱码,当用plsqldev直接插 ...

  5. mysql创建用户、赋予指定权限命令

    1.远程登录mysql mysql -h ip -u root -p 密码 2.创建用户 格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码 ...

  6. js 图片缩显

    <script language="javascript"> var flag=false;  function MyImage(Img){  var image=ne ...

  7. CUDA流(Stream)

    CUDA流表示一个GPU操作队列,该队列中的操作将以添加到流中的先后顺序而依次执行.可以将一个流看做是GPU上的一个任务,不同任务可以并行执行.使用CUDA流,首先要选择一个支持设备重叠(Device ...

  8. Android的DDMS中的Threads的各个字段的含义

    在使用DDMS调试代码时,Threads窗口中各个字段的含义从网上搜了下,如下所示: 该标签页显示了如下信息: ID – a VM-assigned unique thread ID. In Dalv ...

  9. 为什么台湾人工智能可能抢输大陆?(XPU时代来临)

    到了 2020 年,每 3 支手机,就会有一支内建有 AI 芯片. 但目前浮出水面的 AI 芯片新创,几乎都是大陆公司. 为什么台湾这回选择缺席? 「我听说 CPU.GPU,没有听过 NPU? 」11 ...

  10. Swift 1

    Swift 中函数使用指南 关于Swift中的各种函数的使用的总结 前言 时间久了,好多东西我们就会慢慢忘记,在这里总结一下Swift中函数的使用原则,把大部分的函数使用技巧用代码示例来做了演示,但是 ...