【问题标题】:SQL Server : create a trigger on update of "current" table to "history" tableSQL Server:在将“当前”表更新为“历史”表时创建触发器
【发布时间】:2016-05-07 16:08:10
【问题描述】:

我正在从 Oracle 9i db 迁移到 SQL Server,并尝试制定和转换我们必须维护记录历史的一个触发器。 History 表有自己的ID 列,所有其他列与Current 表中的相同。

这是我在 OraDb 中的触发器:(在 OraDb 中,我们使用序列来增加“历史”PK)

CREATE OR REPLACE TRIGGER "RC_CURRENT_T" 
BEFORE INSERT OR UPDATE
ON RC_CURRENT 
FOR EACH ROW 

  DECLARE var_date VARCHAR2(30 BYTE);
  BEGIN
    IF UPDATING THEN
      var_date:=TO_CHAR(CURRENT_DATE, 'MM/DD/YYYY HH24:MI:SS');
      INSERT
      INTO RC_HISTORY
        (
          "ID" ,
          REC_ID ,
          STATUS_DESCR ,
          REQBY_FULLNAME ,
          REQBY_USERNAME ,
          REQBY_EMAIL ,
          REQBY_EMPLID ,
          PCARD_TYPE ,
          BUS_SGMT_DESCR ,
          REQ_TYPE ,
          REQ_CHNGAUTHBY ,
          OP_CNTR_NAME ,
          CARDHOLDER_NAME ,
          CUSTODIAN_NAME ,
          ED_ROLLUP_NUM ,
          CARDHOLDER_ADDRESS ,
          CARDHOLDER_CITY ,
          CARDHOLDER_STATE ,
          CARDHOLDER_ZIP ,
          CARD_NUMBER ,
          GL_CODE ,
          GL_LOCATION ,
          GL_DEPARTMENT ,
          GL_ACCOUNT ,
          GL_SVCSCODE ,
          MONTH_LIMIT ,
          LIMIT_RESTRICTIONS ,
          CARD_LIMIT ,
          REASON_COMMENTS ,
          CREATE_DATE ,
          APPROVER1_NAME ,
          APPROVER1_USERNAME ,
          APPROVER1_EMAIL ,
          APPROVER1_EMPLID ,
          APPROVER1_DATE ,
          APPROVER2_NAME ,
          APPROVER2_USERNAME ,
          APPROVER2_EMAIL ,
          APPROVER2_EMPLID ,
          APPROVER2_DATE ,
          ADMIN_LVL1 ,
          ADMIN_LVL2 ,
          ADMIN_LVL3 ,
          ADMIN_LVL4 ,
          ADMIN_LVL5 ,
          ADMIN_LVL6 ,
          KEYED_DATE ,
          KEYED_BY_NAME ,
          KEYER_CHANGE_TYPE ,
          KEYER_COMMENTS ,
          CARD_STATUS ,
          KEYER_USERNAME ,
          KEYER_EMPLID ,
          USER_FULLNAME,
          OPER_STREET,
          OPER_CITY,
          OPER_STATE,
          OPER_ZIP,
          USER_PHONE,
          USER_EMAIL,
          USER_HYCHY_SETUP,
          USER_ASSIGNED_USERID,
          USER_PROCESS_DATE,
          USER_DISTRIBUTION,
          USER_REQUESTTYPE,
          REC_ENTRY_DATE
        )
        VALUES
        (
          RC_HISTORY_SEQ.nextval ,
          :OLD.REC_ID ,
          :OLD.STATUS_DESCR ,
          :OLD.REQBY_FULLNAME ,
          :OLD.REQBY_USERNAME ,
          :OLD.REQBY_EMAIL ,
          :OLD.REQBY_EMPLID ,
          :OLD.PCARD_TYPE ,
          :OLD.BUS_SGMT_DESCR ,
          :OLD.REQ_TYPE ,
          :OLD.REQ_CHNGAUTHBY ,
          :OLD.OP_CNTR_NAME ,
          :OLD.CARDHOLDER_NAME ,
          :OLD.CUSTODIAN_NAME ,
          :OLD.ED_ROLLUP_NUM ,
          :OLD.CARDHOLDER_ADDRESS ,
          :OLD.CARDHOLDER_CITY ,
          :OLD.CARDHOLDER_STATE ,
          :OLD.CARDHOLDER_ZIP ,
          :OLD.CARD_NUMBER ,
          :OLD.GL_CODE ,
          :OLD.GL_LOCATION ,
          :OLD.GL_DEPARTMENT ,
          :OLD.GL_ACCOUNT ,
          :OLD.GL_SVCSCODE ,
          :OLD.MONTH_LIMIT ,
          :OLD.LIMIT_RESTRICTIONS ,
          :OLD.CARD_LIMIT ,
          :OLD.REASON_COMMENTS ,
          :OLD.CREATE_DATE ,
          :OLD.APPROVER1_NAME ,
          :OLD.APPROVER1_USERNAME ,
          :OLD.APPROVER1_EMAIL ,
          :OLD.APPROVER1_EMPLID ,
          :OLD.APPROVER1_DATE ,
          :OLD.APPROVER2_NAME ,
          :OLD.APPROVER2_USERNAME ,
          :OLD.APPROVER2_EMAIL ,
          :OLD.APPROVER2_EMPLID ,
          :OLD.APPROVER2_DATE ,
          :OLD.ADMIN_LVL1 ,
          :OLD.ADMIN_LVL2 ,
          :OLD.ADMIN_LVL3 ,
          :OLD.ADMIN_LVL4 ,
          :OLD.ADMIN_LVL5 ,
          :OLD.ADMIN_LVL6 ,
          :OLD.KEYED_DATE ,
          :OLD.KEYED_BY_NAME ,
          :OLD.KEYER_CHANGE_TYPE ,
          :OLD.KEYER_COMMENTS ,
          :OLD.CARD_STATUS ,
          :OLD.KEYER_USERNAME ,
          :OLD.KEYER_EMPLID ,
          :OLD.USER_FULLNAME,
          :OLD.OPER_STREET,
          :OLD.OPER_CITY,
          :OLD.OPER_STATE,
          :OLD.OPER_ZIP,
          :OLD.USER_PHONE,
          :OLD.USER_EMAIL,
          :OLD.USER_HYCHY_SETUP,
          :OLD.USER_ASSIGNED_USERID,
          :OLD.USER_PROCESS_DATE,
          :OLD.USER_DISTRIBUTION,
          :OLD.USER_REQUESTTYPE,
          var_date
        ) ;
    END IF;
  END;

我尝试了以下操作,但收到错误消息

INSERT 语句的选择列表包含的项目少于
插入列表。 SELECT 值的数量必须与 INSERT 的数量匹配 列。

代码:

CREATE TRIGGER RC_CURRENT_T 
ON [dbo].[RC_CURRENT] 
FOR UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [dbo].[RC_HISTORY]
    ([REC_ID]
    ,[STATUS_DESCR]
    ,[REQBY_FULLNAME]
    ,[REQBY_USERNAME]
    ,[REQBY_EMAIL]
    ,[REQBY_EMPLID]
    ,[PCARD_TYPE]
    ,[BUS_SGMT_DESCR]
    ,[REQ_TYPE]
    ,[REQ_CHNGAUTHBY]
    ,[OP_CNTR_NAME]
    ,[CARDHOLDER_NAME]
    ,[CUSTODIAN_NAME]
    ,[ED_ROLLUP_NUM]
    ,[CARDHOLDER_ADDRESS]
    ,[CARDHOLDER_CITY]
    ,[CARDHOLDER_STATE]
    ,[CARDHOLDER_ZIP]
    ,[CARD_NUMBER]
    ,[GL_CODE]
    ,[GL_LOCATION]
    ,[GL_DEPARTMENT]
    ,[GL_ACCOUNT]
    ,[GL_SVCSCODE]
    ,[MONTH_LIMIT]
    ,[LIMIT_RESTRICTIONS]
    ,[CARD_LIMIT]
    ,[REASON_COMMENTS]
    ,[CREATE_DATE]
    ,[APPROVER1_NAME]
    ,[APPROVER1_USERNAME]
    ,[APPROVER1_EMAIL]
    ,[APPROVER1_EMPLID]
    ,[APPROVER1_DATE]
    ,[APPROVER2_NAME]
    ,[APPROVER2_USERNAME]
    ,[APPROVER2_EMAIL]
    ,[APPROVER2_EMPLID]
    ,[APPROVER2_DATE]
    ,[ADMIN_LVL1]
    ,[ADMIN_LVL2]
    ,[ADMIN_LVL3]
    ,[ADMIN_LVL4]
    ,[ADMIN_LVL5]
    ,[ADMIN_LVL6]
    ,[KEYED_DATE]
    ,[KEYED_BY_NAME]
    ,[KEYER_CHANGE_TYPE]
    ,[KEYER_COMMENTS]
    ,[CARD_STATUS]
    ,[KEYER_USERNAME]
    ,[KEYER_EMPLID]
    ,[USER_FULLNAME]
    ,[OPER_STREET]
    ,[OPER_CITY]
    ,[OPER_STATE]
    ,[OPER_ZIP]
    ,[USER_PHONE]
    ,[USER_EMAIL]
    ,[USER_HYCHY_SETUP]
    ,[USER_ASSIGNED_USERID]
    ,[USER_PROCESS_DATE]
    ,[USER_DISTRIBUTION]
    ,[USER_REQUESTTYPE]
    ,[REC_ENTRY_DATE]
    )
    SELECT * FROM RC_CURRENT
END
GO

出于报告目的,我需要在历史记录表中维护单独的 ID。

非常感谢任何帮助。

谢谢。

【问题讨论】:

  • 您可以尝试明确指定选择的列吗?此外,您的选择必须从“更新”表中读取(即更新的记录)

标签: sql-server oracle triggers


【解决方案1】:

查看旧触发器(和错误消息)RC_HISTORYRC_CURRENT 相比有 1 个额外字段,因此您有两个选择。

  1. 如果[REC_ID] 是具有自动增量的标识列,您只需将其从要插入的列列表中删除

    INSERT INTO [dbo].[RC_HISTORY]
    ([STATUS_DESCR]
    ,[REQBY_FULLNAME]
    ,[REQBY_USERNAME]
    ...
    
  2. 如果[REC_ID] 未设置为自动递增,则您必须提供一个值以插入列中

    SELECT (SELECT MAX([REC_ID])+1 FROM RC_HISTORY), * FROM RC_CURRENT
    

我建议您尝试第一个选项并将该列设置为标识列(如果还没有),我还建议您也使用命名列而不是 * 作为选择值。

【讨论】:

  • 除了其他 cmets,我强烈建议您不要将日期存储为 varchar。 oracle 和 sql server 都有适当的数据类型来存储日期。将数据存储为错误的数据类型是导致持续头痛的秘诀,如果不是彻头彻尾的灾难的话。这是任何 rdbms 的基本设计缺陷。
  • 谢谢 benni_mac_b 和 EdStevens。我继续明确地输入每一列。 REC_ID(key) 是“Current”表的 ID 列,但“History”表有自己的 ID(key) 列,REC_ID 在 REC_ID 上有 Current(one)->History(many) 关系。跨度>
猜你喜欢
  • 2020-01-07
  • 2011-01-15
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 2016-11-03
  • 2015-11-06
  • 2012-03-13
  • 2022-01-01
相关资源
最近更新 更多