【问题标题】:sql server - trigger with cursorsql server - 用光标触发
【发布时间】:2017-11-30 11:18:50
【问题描述】:

我正在尝试设计一个接收订单行的登陆表,然后触发器会将数据发送到适当的表(即客户、订单、订单行)。

我可以在 MySQL 中使用新旧关键字轻松完成此操作,但是我在 SQL Server 中遇到了一些问题。

首先 - 这是解决此类问题的最佳方法吗?

其次,如果是,我尝试创建一个触发器,该触发器使用游标遍历 SQL Server 中插入的表。不幸的是,我不断收到错误

消息 16916,级别 16,状态 1,过程 _raw_b2c_lines_ins,第 17 行 [批处理开始第 6 行]
名为“ins_cusor”的游标不存在

我附上了下面的代码(删除了订单和订单行表的代码以简化)

CREATE OR ALTER TRIGGER zap._raw_b2c_lines_ins
            on zap._b2c
            after insert
            as
            begin

            declare @v_phone_cleansed varchar
            ,   @phone varchar
            ,   @v_curr_cust_id varchar
            ,   @customer_key varchar
            ,   @t_order_id int
            ,   @customer_id varchar
            ,   @t_raw_id int
            --
            declare ins_cursor CURSOR FOR SELECT t_raw_id from inserted;
            --

            OPEN ins_cusor;

            FETCH NEXT from ins_cursor INTO @t_raw_id;

            WHILE (@@FETCH_STATUS = 0)
            --
            BEGIN

            set @v_phone_cleansed = dbo.CleanNumber((select billing_phone 
            from    inserted 
            where   t_raw_id = @t_raw_id
            ));
            set @v_curr_cust_id = (select  isnull(max(t_customer_id),0) +1 from sales.b2c_customer);
            --
            if exists(  select  1 
            from    sales.b2c_customer c
            join    inserted i
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) =        lower(i.billing_email)
            and     (   lower(c.country) != lower(i.billing_country)
            or  lower(c.city) !=    lower(i.billing_city)
            or  c.phone_cleansed != @v_phone_cleansed   
            )
            and     c.current_record = 1
            and     i.t_raw_id = @t_raw_id  ) 
            --
            Begin
            set @customer_key = (   select  top 1 customer_key
            from    sales.b2c_customer c
            join    inserted i
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) =        lower(i.billing_email)
            and     (   lower(c.country)!=  lower(i.billing_country)
            or  lower(c.city) !=    lower(i.billing_city)
            or  c.phone_cleansed != @v_phone_cleansed   
            )
            and     c.current_record = 1    
            and     i.t_raw_id = @t_raw_id
            );
            --
            update sales.b2c_customer 
            set current_record = 0 
            where   exists (select  *
            from    sales.b2c_customer c
            join    inserted i
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) =        lower(i.billing_email)
            and     (   lower(c.country) != lower(i.billing_country)
            or  lower(c.city) !=    lower(i.billing_city)
            or  c.phone_cleansed != @v_phone_cleansed
            )
            and     c.current_record = 1
            and     i.t_raw_id = @t_raw_id
            )

            insert into sales.b2c_customer(
            customer_key
            ,   last_name
            ,   first_name
            ,   email
            ,   country
            ,   city
            ,   phone
            ,   phone_cleansed
            ,   current_record
            ) select    @customer_key
            ,   dbo.InitCap(i.billing_last_name)
            ,   dbo.InitCap(i.billing_first_name)
            ,   i.billing_email
            ,   i.billing_country
            ,   dbo.InitCap(i.billing_city)
            ,   i.billing_phone
            ,   @v_phone_cleansed
            ,   1
            from    inserted i
            where   i.t_raw_id = @t_raw_id
            ;
            --
            end
            --
            if exists(  select  1 
            from    sales.b2c_customer c
            join    inserted i
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) !=       lower(i.billing_email)
            and     lower(c.country) =      lower(i.billing_country)
            and     lower(c.city) =         lower(i.billing_city)
            and     lower(c.phone_cleansed) =   @v_phone_cleansed
            and     current_record = 1
            and     i.t_raw_id = @t_raw_id
            ) 
            --
            Begin
            --
            set     @customer_key = (   select  top 1 customer_key
            from    sales.b2c_customer c
            join    inserted i 
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) !=       lower(i.billing_email)
            and     lower(c.country) =      lower(i.billing_country)
            and     lower(c.city) =         lower(i.billing_city)
            and     c.phone_cleansed =  @v_phone_cleansed
            and     i.t_raw_id = @t_raw_id
            );
            update sales.b2c_customer 
            set current_record = 0 
            where   exists (select  *
            from    sales.b2c_customer c
            join    inserted i
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) !=       lower(i.billing_email)
            and     lower(c.country) =  lower(i.billing_country)
            and     lower(c.city) =     lower(i.billing_city)
            and     c.phone_cleansed =  @v_phone_cleansed
            and     c.current_record = 1
            and     i.t_raw_id = @t_raw_id
            )


            insert into sales.b2c_customer(
            customer_key
            ,   last_name
            ,   first_name
            ,   email
            ,   country
            ,   city
            ,   phone
            ,   phone_cleansed
            ,   current_record
            )   select  @customer_key
            ,       dbo.InitCap(i.billing_last_name)
            ,       dbo.InitCap(i.billing_first_name)
            ,       i.billing_email
            ,       i.billing_country
            ,       dbo.InitCap(i.billing_city)
            ,       i.billing_phone
            ,       @v_phone_cleansed
            ,       1
            from    inserted i
            where   i.t_raw_id = @t_raw_id
            --
            end
            --                    
            if not exists (
            select  1 
            from    sales.b2c_customer c
            join    inserted i 
            on      lower(c.first_name) =   lower(i.billing_first_name)
            and     lower(c.last_name) =    lower(i.billing_last_name)
            and     lower(c.email) =        lower(i.billing_email)
            and     lower(c.country) =      lower(i.billing_country)
            and     lower(c.city) =         lower(i.billing_city)
            and     c.phone_cleansed =  @v_phone_cleansed
            and     c.current_record = 1
            and     i.t_raw_id = @t_raw_id
            ) 
            --
            Begin
            --
            insert into sales.b2c_customer( customer_key
            ,   last_name
            ,   first_name
            ,   email
            ,   country
            ,   city
            ,   phone
            ,   phone_cleansed
            ,   current_record
            )   select concat(lower(i.billing_first_name), lower(i.billing_last_name), @v_curr_cust_id)
            ,   dbo.InitCap(i.billing_last_name)
            ,   dbo.InitCap(i.billing_first_name)
            ,   i.billing_email
            ,   i.billing_country
            ,   dbo.InitCap(i.billing_city)
            ,   i.billing_phone
            ,   @v_phone_cleansed
            ,   1
            from inserted i 
            where i.t_raw_id = @t_raw_id;
            --
            end 
            --

            FETCH NEXT from ins_cursor INTO @t_raw_id;

            end

            close ins_cursor; 
            deallocate ins_cursor;
            end

【问题讨论】:

  • 所以我发现了拼写错误...这就是为什么我会收到错误...我对第一个问题的任何错误都是错误的?是我想要实现的最佳方法吗?
  • 输入 OPEN ins_cursor; 而不是 OPEN ins_cusor;
  • Bad habits to kick : declaring VARCHAR without (length) - 您应该始终为您使用的任何varchar 变量和参数提供长度。否则,您最终会得到只有一个字符长的 SQL 变量——通常不是您想要的.....
  • 哦,我的,光标在触发器中!为什么需要遍历行?你可以使用inserted来合并你需要的表。
  • 这是最好的方法吗?如果不充分了解您的架构以及导致您使用此“解决方案”的原因,那么这个问题就无法准确评估。顺便说一句,我会说不。但这是一个纯粹的猜测。并且在 sql server 中编写触发器很困难 - 这对于那些没有 tsql 经验且没有正确心态的人来说不是什么事情。 sql server 中的触发器以批处理级别执行,并且必须处理由触发 statememt 生成的任意数量的行。

标签: sql-server triggers cursor


【解决方案1】:

首先以该名称创建过程,然后执行 因为它找不到那个光标。

【讨论】:

    猜你喜欢
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多