精华内容
下载资源
问答
  • 软件开发过程中不仅要考虑软件功能实现,还要考虑软件...SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序事先定义查询语句的结尾上添加额外SQL语句,以此来实现欺骗数

    软件开发过程中不仅要考虑软件的功能实现,还要考虑软件的安全性,如果一个软件系统安全性做得不好,一旦被黑客攻击,后果不堪设想。对于B/S系统,SQL注入攻击就是一个常见的安全隐患,下面我们来看下如何在日常开发中避免SQL注入攻击。

    SQL注入简介
    SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
    这里写图片描述

    这里我们举一个比较常见的例子来简要说明一下sql注入的原理。假如我们有一个users表,里面有两个字段username和password。在我们的java代码中我们初学者都习惯用sql拼接的方式进行用户验证。比如:”select id from users where username = ‘”+username +”’ and password = ‘” + password +”’” 这里的username和password都是我们存取从web表单获得的数据。下面我们来看一下一种简单的注入,如果我们在表单中username的输入框中输入’ or 1=1– ,password的表单中随便输入一些东西,假如这里输入123.此时我们所要执行的sql语句就变成了select id from users where username = ” or 1=1– and password = ‘123’,我们来看一下这个sql,因为1=1是true,后面 and password = ‘123’被注释掉了。所以这里完全跳过了sql验证。

    SQL注入预防
    防止SQL注入的方式的原理就是转义特殊符号,可以通过正则表达式对参数进行过滤,或者将查询参数动态绑定。下面是一个使用JDBC查询的例子:

    PrepareStatement pre=connection.prepare(“select * from User where user.name=?”); 
    pre.setString(1,”zhaoxin”); 
    ResultSet rs=pre.executeQuery(); 

    在Hibernate中也提供了类似这种的查询参数绑定功能,而且在Hibernate中对这个功能还提供了比传统JDBC操作丰富的多的特性。

    1,按参数名称绑定: ,
    在HQL语句中定义命名参数要用”:”开头,形式如下:

    Query query=session.createQuery(“from User user where user.name=:customername and user:customerage=:age ”); 
    query.setString(“customername”,name); 
    query.setInteger(“customerage”,age); 

    上面代码中用:customername和:customerage分别定义了命名参数customername和customerage,然后用Query接口的setXXX()方法设定名参数值,setXXX()方法包含两个参数,分别是命名参数名称和命名参数实际值。

    2,按参数位置邦定:
    在HQL查询语句中用”?”来定义参数位置,形式如下:

    Query query=session.createQuery(“from User user where user.name=? and user.age =? ”); 
    query.setString(0,name); 
    query.setInteger(1,age); 

    同样使用setXXX()方法设定绑定参数,只不过这时setXXX()方法的第一个参数代表邦定参数在HQL语句中出现的位置编号(由0开始编号),第二个参数仍然代表参数实际值。

    注:在实际开发中,提倡使用按名称邦定命名参数,因为这不但可以提供非常好的程序可读性,而且也提高了程序的易维护性,因为当查询参数的位置发生改变时,按名称邦定名参数的方式中是不需要调整程序代码的。

    3,setParameter()方法: ,
    在Hibernate的HQL查询中可以通过setParameter()方法邦定任意类型的参数,如下代码:

    String hql=”from User user where user.name=:customername ”; 
    Query query=session.createQuery(hql); 
    query.setParameter(“customername”,name,Hibernate.STRING); 

    如上面代码所示,setParameter()方法包含三个参数,分别是命名参数名称,命名参数实际值,以及命名参数映射类型。对于某些参数类型setParameter()方法可以更具参数值的Java类型,猜测出对应的映射类型,因此这时不需要显示写出映射类型,像上面的例子,可以直接这样写: query.setParameter(“customername”,name);但是对于一些类型就必须写明映射类型,比如java.util.Date类型,因为它会对应Hibernate的多种映射类型,比如Hibernate.DATA或者Hibernate.TIMESTAMP。

    4,setProperties()方法: ,
    在Hibernate中可以使用setProperties()方法,将命名参数与一个对象的属性值绑定在一起,如下程序代码:

    Customer customer=new Customer(); 
    customer.setName(“pansl”); 
    customer.setAge(80); 
    Query query=session.createQuery(“from Customer c where c.name=:name and c.age=:age ”); 
    query.setProperties(customer); 

    setProperties()方法会自动将customer对象实例的属性值匹配到命名参数上,但是要求命名参数名称必须要与实体对象相应的属性同名。

    提倡大家使用第一种方法,代码清晰易懂。

    展开全文
  • 注意不同的是被单引号引出的字符串是以字面定义的,而双引号引出的字符串可以被扩展。反斜杠(\)可以被用来分割某些特殊字符。举例如下: $first = 'Hello'; $second = "World"; $full1 = "$first $second"; # ...
  • 触发器限制

    2010-10-14 15:19:00
    在PL/SQL块可以使用的所有语句在触发器主体中都是合法的,但是要受到下面限制的约束: 触发器不应该使用事务控制语句—COMMIT、ROLLBACK或SAVEPOINT。触发器作为触发语句执行的一部分被点火,它和触发语句在...

    触发器的主体是一个PL/SQL块。在PL/SQL块中可以使用的所有语句在触发器主体中都是合法的,但是要受到下面限制的约束:

    触发器不应该使用事务控制语句—COMMIT、ROLLBACK或SAVEPOINT。触发器作为触发语句执行的一部分被点火,它和触发语句在同一个事务中。当触发语句被提交或撤回提交时,触发器的工作也相应被提交会撤回提交。由触发器主体调用的任何过程和函数都不能使用事务控制语句。触发器主体不能声明任何LONG或者LONG RAW变量。而且,:new和:old不能指向定义触发器的表中的LONG和LONG RAW列。触发器主体可以访问的表有所限制。
    触发器P-Code
    当包或者子程序存储在数据字典中时,存储的除了该对象的源代码还有经过编译的p-code。但是对于触发器来说就不是这样的。在数据字典中唯一存储的是触发器的源代码,而不是p-code。结果,每次当从数据字典中重新读出触发器时,必须要进行编译。这对触发器的定义和使用的方式不会带来什么影响,但是会影响触发器的性能

    INSTEAD-OF触发器必须是行级的

    INSTEAD-OF触发器仅可以定义在视图上(关系型的或对象),

    展开全文
  • 本书以问答形式组织内容,讨论了学习或使用C语言的过程中经常遇到一些问题。书列出了C用户经常问400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面主题,并分别...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    这样是合法的和可移植的吗? 23  2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明不能这样做? 25 2.9 为什么不能用内建的==和!=操作符比较结构? 26 2.10 结构传递和返回是如何实现...
  • 2.17 C语言有和Pascalwith等价的语句吗? 2.18 既然数组名可以用作数组基地址,为什么对结构不能这样? 2.19 程序运行正确,但退出时却“coredump”(核心转储)了,怎么回事? 联合 2.20 结构和联合有什么...
  • 这样是合法的和可移植的吗? 2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1;却明确说明不能这样做? 2.9 为什么不能用内建的==和!=操作符比较结构? 2.10 结构传递和返回是如何实现的? 2.11 如何...
  • 这样是合法的和可移植的吗? 23  2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明不能这样做? 25 2.9 为什么不能用内建的==和!=操作符比较结构? 26 2.10 结构传递和返回是如何实现...
  • 这样是合法的和可移植的吗? 2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明不能这样做? 2.9 为什么不能用内建的==和!=操作符比较结构? 2.10 结构传递和返回是如何实现的? 2.11 如何向...
  • 当使用下面的一种或多种数据修改操作在指定表对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可以查询其它表,而且可以包含复杂 SQL 语句。它们主要用于强制复杂业务规则或要求。  ...
    引用:
    定义:
      触发器是一种特殊类型的存储过程,不由用户直接调用。当使用下面的一种或多种数据修改操作在指定表中对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。

      触发器一个应用就是保持和维护数据的完整性及合法性,那么怎么来理解呢?就是说你可以在程序里提交任意数据,然后由触发器来判断数据的完整性及合法性,当然这里只是举例说明,实际应用中不推荐这样用,应该由应用程序来验证数据的完整性及合法性。

      下面我还是以实例的方式来描述触发器的应用。

      设:当前数据库中有“uMateriel”和“uRecord”两张表,他们分别用来保存物品信息和物品的出入库记录信息,结构如下

    引用:
    uMateriel
    ----------------
    mId   int
    mName  nvarchar(40)
    mNum   int DEFAULT 0

    uRecord
    ----------------
    rId   int
    mId   int
    rNum   int
    rDate  datetime DEFAULT GetDate()
    rMode  bit DEFAULT 0

      好了,数据表已经有了,现在看一下实际的应用。

      现在,我们要购入物品A,数量100,时间为当天,已知物品A的编号为1,那么通常我们需要做以下两个步骤:

    引用:
    1、在 uRecord 记录表中增加一条物品A的购入记录:
      INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)

    2、更新 uMateriel 物品库存表中物品A的数量:
      UPDATE uMateriel SET mNum = mNum + 100 WHERE mId=1

      也就是说代码中要先后处理以上两条语句,才能保证库存的准确性,以ASP代码为例:

    引用:
    On Error Resume Next

    '// 设 adoConn 为已经连接的 ADODB.Connection 对象
    With adoConn
            '// 事务开始,因为涉及到多步数据更新操作,所以在这里使用事务
            .BeginTrans
            '// 插入物品入库记录
            .Execute("INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")

            '// 更新物品库存记录
            .Execute("UPDATE uMateriel SET mNum = mNum + 100 WHERE mId=1")

            '// 判断是否产生了错误
            If Err.Number <> 0 Then
                    '// 如果有错误,事务回滚
                    .RollbackTrans
                    Response.Write "错误!"
                    Err.Clear
            Else
                    '// 如果没有错误,则提交事务
                    .CommitTrans
            End If
    End With

      以上代码可以更新一条入库记录了,但是我们今天要了解的是触发器的应用,那么要在触发器里写什么内容可以简化以上代码呢?下面来创建一个触发器。

      创建触发器的语法很长,简化为:

    引用:
    CREATE TRIGGER 触发器名 ON 表名/视图名
    { FOR | AFTER | INSTEAD OF } { [DELETE] [,] [INSERT] [,] [UPDATE] }
    AS
      触发器内容(SQL 语句)



    引用:
    SQL SERVER 联机丛书的描述:
    AFTER
      指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。
      如果仅指定 FOR 关键字,则 AFTER 是默认设置。
      不能在视图上定义 AFTER 触发器。

    INSTEAD OF
      指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。
      在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。
      INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定了 WITH CHECK OPTION 选项的可更新视图添加 INSTEAD OF 触发器,SQL Server 将产生一个错误。用户必须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。

    { [DELETE] [,] [INSERT] [,] [UPDATE] }
      是指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。
      对于 INSTEAD OF 触发器,不允许在具有 ON DELETE 级联操作引用关系的表上使用 DELETE 选项。同样,也不允许在具有 ON UPDATE 级联操作引用关系的表上使用 UPDATE 选项。

      现在根据上面的语法我们建立一个触发器(注意一点,触发器是附于一张表或视图的,所以只能在表里建立或在查询分析器里建立),这个触发器的功能就是自动更新库存数量

    引用:
    CREATE TRIGGER [trUpdateMaterielNum] ON [dbo].[uRecord]
    -- 表明在插入记录之后执行这个触发器
    AFTER INSERT
    AS
    -- 当前更新的编号
    DECLARE @intID                int
    -- 当前更新的数量
    DECLARE @intNum        int
    -- 当前模式
    DECLARE @intMode        int

    -- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
    IF @@ROWCOUNT >0
    BEGIN
            -- 取得当前插入的物品编号和数量,Inserted 表用于存储 INSERT 和 UPDATE 语句所影响的行的副本。
            SELECT @intID=mId,@intNum=rNum,@intMode=rMode FROM Inserted

            -- 判断当前模式(0为入库,1为出库)来更新当前物品的数量
            IF @intMode = 0
                    UPDATE uMateriel SET mNum = mNum + @intNum WHERE mId=@intID
            ELSE
                    UPDATE uMateriel SET mNum = mNum - @intNum WHERE mId=@intID
    END

      我们现在来了解一下这个触发器,首先使用 CREATE TRIGGER 语句定义一个基于 uRecord 表的触发器 trUpdateMaterielNum,AFTER INSERT 表明这个触发器会在插入记录之后执行,也就是说当我们在程序里执行 INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0) 这条语句之后,trUpdateMaterielNum这个触发器里的内容就会被自动执行,也就是说库存将会被自动更新了。现在我们更改一下ASP的代码

    引用:
    On Error Resume Next

    '// 设 adoConn 为已经连接的 ADODB.Connection 对象
    '// 插入物品入库记录

    adoConn.Execute("INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")

    '// 判断是否产生了错误
    If Err.Number <> 0 Then
            Response.Write "错误!"
            Err.Clear
    End If

      是不是简化了很多呢,是的,在这里已经不用考虑库存方面,只需要插入流水帐就可以了,库存更新就交由触发器来处理。

      以上的例子是触发器的其中一个应用,在触发器的参数中还有 DELETE、UPDATE,他们分别在删除和更新时或之后执行。下面看一个删除时的触发器例子。

      我们在数据库中增加一个表,用来记录日志,其结构如下

    引用:
    uSysLog
    --------------
    lId                int
    lEvent        nvarchar(200)
    lTime                datetime DEFAULT GetDate()

      现在假设这张表是用来记录系统的日志用的,当我们删除一条流水帐时,往日志表里记录一条事件,那么我们来创建一个基于 uRecord 表的删除时的触发器

    引用:
    CREATE TRIGGER [trDeleteRecord] ON [dbo].[uRecord]
    -- 表明在插入记录之后执行这个触发器
    FOR DELETE
    AS
    -- 当前删除的流水号
    DECLARE @intID                int
    -- 当前删除的数量
    DECLARE @intNum        int
    -- 当前模式
    DECLARE @intMode        int

    -- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
    IF @@ROWCOUNT >0
    BEGIN
            -- 取得当前删除的行信息,Deleted 表用于存储 DELETE 和 UPDATE 语句所影响的行的复本。
            SELECT @intID=rId,@intNum=rNum,@intMode=rMode FROM Deleted

            -- 向日志表中插入一条简单的删除事件日志
            INSERT INTO uSysLog (lEvent) VALUES ('用户删除了流水号为:' + CAST(@intID as nvarchar(20) + ',数量:' + CAST(@intNum as nvarchar(20) + ',方向:' + CASE @intMode WHEN 0 THEN '入库' ELSE '出库' END)
    END

      建立好触发器后,现在只要我们删除 uRecord 表中的一条记录,就会在系统日志中增加一条事件日志。 

    转载于:https://www.cnblogs.com/laino/archive/2009/05/23/1487408.html

    展开全文
  • 引用:定义: 触发器是一种特殊类型存储过程,不由用户直接调用。当使用下面的一种或多种数据修改操作在指定表对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可以查询其它表,而且可以包含...
    引用:
    定义:
      触发器是一种特殊类型的存储过程,不由用户直接调用。当使用下面的一种或多种数据修改操作在指定表中对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。

      触发器一个应用就是保持和维护数据的完整性及合法性,那么怎么来理解呢?就是说你可以在程序里提交任意数据,然后由触发器来判断数据的完整性及合法性,当然这里只是举例说明,实际应用中不推荐这样用,应该由应用程序来验证数据的完整性及合法性。

      下面我还是以实例的方式来描述触发器的应用。

      设:当前数据库中有“uMateriel”和“uRecord”两张表,他们分别用来保存物品信息和物品的出入库记录信息,结构如下

    引用:
    uMateriel
    ----------------
    mId   int
    mName  nvarchar(40)
    mNum   int DEFAULT 0

    uRecord
    ----------------
    rId   int
    mId   int
    rNum   int
    rDate  datetime DEFAULT GetDate()
    rMode  bit DEFAULT 0

      好了,数据表已经有了,现在看一下实际的应用。

      现在,我们要购入物品A,数量100,时间为当天,已知物品A的编号为1,那么通常我们需要做以下两个步骤:

    引用:
    1、在 uRecord 记录表中增加一条物品A的购入记录:
      INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)

    2、更新 uMateriel 物品库存表中物品A的数量:
      UPDATE uMateriel SET mNum = mNum + 100 WHERE mId=1

      也就是说代码中要先后处理以上两条语句,才能保证库存的准确性,以ASP代码为例:

    引用:
    On Error Resume Next

    '// 设 adoConn 为已经连接的 ADODB.Connection 对象
    With adoConn
            '// 事务开始,因为涉及到多步数据更新操作,所以在这里使用事务
            .BeginTrans
            '// 插入物品入库记录
            .Execute("INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")

            '// 更新物品库存记录
            .Execute("UPDATE uMateriel SET mNum = mNum + 100 WHERE mId=1")

            '// 判断是否产生了错误
            If Err.Number <> 0 Then
                    '// 如果有错误,事务回滚
                    .RollbackTrans
                    Response.Write "错误!"
                    Err.Clear
            Else
                    '// 如果没有错误,则提交事务
                    .CommitTrans
            End If
    End With

      以上代码可以更新一条入库记录了,但是我们今天要了解的是触发器的应用,那么要在触发器里写什么内容可以简化以上代码呢?下面来创建一个触发器。

      创建触发器的语法很长,简化为:

    引用:
    CREATE TRIGGER 触发器名 ON 表名/视图名
    { FOR | AFTER | INSTEAD OF } { [DELETE] [,] [INSERT] [,] [UPDATE] }
    AS
      触发器内容(SQL 语句)



    引用:
    SQL SERVER 联机丛书的描述:
    AFTER
      指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。
      如果仅指定 FOR 关键字,则 AFTER 是默认设置。
      不能在视图上定义 AFTER 触发器。

    INSTEAD OF
      指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。
      在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。
      INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定了 WITH CHECK OPTION 选项的可更新视图添加 INSTEAD OF 触发器,SQL Server 将产生一个错误。用户必须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。

    { [DELETE] [,] [INSERT] [,] [UPDATE] }
      是指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。
      对于 INSTEAD OF 触发器,不允许在具有 ON DELETE 级联操作引用关系的表上使用 DELETE 选项。同样,也不允许在具有 ON UPDATE 级联操作引用关系的表上使用 UPDATE 选项。

      现在根据上面的语法我们建立一个触发器(注意一点,触发器是附于一张表或视图的,所以只能在表里建立或在查询分析器里建立),这个触发器的功能就是自动更新库存数量

    引用:
    CREATE TRIGGER [trUpdateMaterielNum] ON [dbo].[uRecord]
    -- 表明在插入记录之后执行这个触发器
    AFTER INSERT
    AS
    -- 当前更新的编号
    DECLARE @intID                int
    -- 当前更新的数量
    DECLARE @intNum        int
    -- 当前模式
    DECLARE @intMode        int

    -- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
    IF @@ROWCOUNT >0
    BEGIN
            -- 取得当前插入的物品编号和数量,Inserted 表用于存储 INSERT 和 UPDATE 语句所影响的行的副本。
            SELECT @intID=mId,@intNum=rNum,@intMode=rMode FROM Inserted

            -- 判断当前模式(0为入库,1为出库)来更新当前物品的数量
            IF @intMode = 0
                    UPDATE uMateriel SET mNum = mNum + @intNum WHERE mId=@intID
            ELSE
                    UPDATE uMateriel SET mNum = mNum - @intNum WHERE mId=@intID
    END

      我们现在来了解一下这个触发器,首先使用 CREATE TRIGGER 语句定义一个基于 uRecord 表的触发器 trUpdateMaterielNum,AFTER INSERT 表明这个触发器会在插入记录之后执行,也就是说当我们在程序里执行 INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0) 这条语句之后,trUpdateMaterielNum这个触发器里的内容就会被自动执行,也就是说库存将会被自动更新了。现在我们更改一下ASP的代码

    引用:
    On Error Resume Next

    '// 设 adoConn 为已经连接的 ADODB.Connection 对象
    '// 插入物品入库记录

    adoConn.Execute("INSERT INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")

    '// 判断是否产生了错误
    If Err.Number <> 0 Then
            Response.Write "错误!"
            Err.Clear
    End If

      是不是简化了很多呢,是的,在这里已经不用考虑库存方面,只需要插入流水帐就可以了,库存更新就交由触发器来处理。

      以上的例子是触发器的其中一个应用,在触发器的参数中还有 DELETE、UPDATE,他们分别在删除和更新时或之后执行。下面看一个删除时的触发器例子。

      我们在数据库中增加一个表,用来记录日志,其结构如下

    引用:
    uSysLog
    --------------
    lId                int
    lEvent        nvarchar(200)
    lTime                datetime DEFAULT GetDate()

      现在假设这张表是用来记录系统的日志用的,当我们删除一条流水帐时,往日志表里记录一条事件,那么我们来创建一个基于 uRecord 表的删除时的触发器

    引用:
    CREATE TRIGGER [trDeleteRecord] ON [dbo].[uRecord]
    -- 表明在插入记录之后执行这个触发器
    FOR DELETE
    AS
    -- 当前删除的流水号
    DECLARE @intID                int
    -- 当前删除的数量
    DECLARE @intNum        int
    -- 当前模式
    DECLARE @intMode        int

    -- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
    IF @@ROWCOUNT >0
    BEGIN
            -- 取得当前删除的行信息,Deleted 表用于存储 DELETE 和 UPDATE 语句所影响的行的复本。
            SELECT @intID=rId,@intNum=rNum,@intMode=rMode FROM Deleted

            -- 向日志表中插入一条简单的删除事件日志
            INSERT INTO uSysLog (lEvent) VALUES ('用户删除了流水号为:' + CAST(@intID as nvarchar(20) + ',数量:' + CAST(@intNum as nvarchar(20) + ',方向:' + CASE @intMode WHEN 0 THEN '入库' ELSE '出库' END)
    END

      建立好触发器后,现在只要我们删除 uRecord 表中的一条记录,就会在系统日志中增加一条事件日志。 
    展开全文
  • 本人正在用,很好用,是中文免安装版下面是详细介绍: PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元开发。如今,有越来越多商业逻辑和应用逻辑转向了Oracle Server,因此,PL/...
  • 可以在管理页面上添加博文分类,可以上传图片和游览自己相册,在上传过程中可以将一张图片定义为自己签名,在个人管理页面注册用户还可以修改自己个人信息。博文管理,友情链接管理及博文分类管理,用例图...
  • 遗憾的是,由于C/C++ 语言的编译特性,Visual C++并没有提供类似的可以替代的现成的数据类型,于是我们只能自己想办法去构造这样一个虚类(或者结构体),这里我们使用标识 Matrix 命名其类型。这个自己构造的 ...
  • 虽然其除了语法标签以外的代码都是合法的 HTML 字符串,但是我们的目的是把它编译成返回 Virtual-DOM 的 render 函数,在构建 Virtual-DOM 的时候,你需要知道元素的 tagName、属性等信息,...
  • (50) 数据库概念设计的过程中,视图设计一般有三种设计次序,以下各项不对的是(D) 注:P127,要牢记 A. 自顶向下 B. 由底向上 C. 由内向外 D. 由整体到局部 (51) 在计算机,算法是指(C) A. 查询方法 B. 加工方法...
  • (7) 在软件开发下面任务不属于设计阶段的是______。(D) A. 数据结构设计 B. 给出系统模块结构 C. 定义模块算法 D. 定义需求并建立系统模型 (8) 数据库系统的核心是______。(B) A. 数据模型 B. 数据库管理系统 C....
  • 如对printf语句中的++i,--i,i++,i--从左至右求值,结果应为: 9 8 8 9  应特别注意的是,无论是从左至右求值, 还是自右至左求值,其输出顺序都是不变的, 即输出顺序总是和实参表中实参的顺序相同。由于Turbo C...
  • C#数据结构

    2013-12-10 11:49:54
    一个算法应该具有很强的容错能力,当输入不合法的数 据时,算法应当能做适当的处理,使得不至于引起严重的后果。健壮性要求表明 算法要全面细致地考虑所有可能出现的边界情况和异常情况,并对这些边界情况 和异常...
  • 下面的说法正确的是:(选择1项) A) 程序运行到第6行会出现编译错误,因为c为char类型,不能把一个汉字赋给一个字符型。 B) 程序运行到第7行会出现编译错误,因为字符型与整型不能进行加法运算。 C) 程序能够正常...
  • 此时打印的是实例变量,而非局部变量,即定义在类而非方法的变量。 This.number表示实例变量。 谁调用this.number那么谁即为当前(this)对象的number方法。 封装:使对象的属性尽可能私有,对象的方法尽可能的...
  • 你必须知道495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    3.12 我需要根据条件把一个复杂表达式赋值给两个变量中的一 个。可以用下边这样代码吗? ((condition) ? a : b) = complicated expression; . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 目录iii ...
  • 软件测试规范

    2018-04-23 09:16:12
    1.语句覆盖 ............................................................................................................................................ 10 2.判定理盖 .....................................
  • 3.以下的变量定义语句中合法的是( )。 A) float $_*5= 3.4F; B) byte b1= 15678; C) double a =Double. MAX_VALUE; D) int _abc_ = 3721L; 4.以下字符常量中不合法的是( )。 A) '|' B) '\'' C) "\n" D) '我' 5....
  •  上例程序执行过程是,首先在屏幕上显示提示串,请用户输入两个数,回车后由scanf函数语句接收这两个数送入变量x,y,然后调用max函数,并把x,y 值传送给max函数参数a,b。在max函数比较a,b大小,把大...
  • Program, _lock, test2, A_B_C_D是合法的标识符,其它的不是。 2-3 例2.1每条语句的作用是什么? #include void main(void) { cout!\n"; cout!\n"; } 解: #include <iostream.h> //指示编译器将文件iostream...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    18.2 在 C #代码调用 C++和 VB 编写组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...

空空如也

空空如也

1 2 3
收藏数 49
精华内容 19
关键字:

下面过程定义语句中合法的是