加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql-server – 如何在T-SQL / SQL Server中为超级/子类型(继承)

发布时间:2021-01-18 06:27:53 所属栏目:编程 来源:网络整理
导读:这是在Azure上. 我有一个超范例实体和几个子范例实体,后者必要从每个插入的超范例实体的主键获取其外键.在Oracle中,我行使BEFORE INSERT触发器来完成此使命.如安在SQL Server / T-SQL中实现这一方针? DDL CREATE TABLE super ( super_id int IDENTITY(1,1),s

这是在Azure上.

我有一个超范例实体和几个子范例实体,后者必要从每个插入的超范例实体的主键获取其外键.在Oracle中,我行使BEFORE INSERT触发器来完成此使命.如安在SQL Server / T-SQL中实现这一方针?

DDL

CREATE TABLE super (
 super_id int IDENTITY(1,1),subtype_discriminator char(4) CHECK (subtype_discriminator IN ('SUB1','SUB2'),CONSTRAINT super_id_pk PRIMARY KEY (super_id)
);
CREATE TABLE sub1 (
 sub_id int IDENTITY(1,super_id int NOT NULL,CONSTRAINT sub_id_pk PRIMARY KEY (sub_id),CONSTRAINT sub_super_id_fk FOREIGN KEY (super_id) REFERENCES super (super_id)
);

我但愿插入到sub1中以触发一个现实将值插入super的触发器,并行使天生的super_id放入sub1.

在Oracle中,这可以通过以下方法完成:

CREATE TRIGGER sub_trg
    BEFORE INSERT ON sub1
    FOR EACH ROW
DECLARE
    v_super_id int; //Ignore the fact that I could have used super_id_seq.CURRVAL
BEGIN
    INSERT INTO super (super_id,subtype_discriminator) 
        VALUES (super_id_seq.NEXTVAL,'SUB1') 
        RETURNING super_id INTO v_super_id;
    :NEW.super_id := v_super_id;
END;

鉴于T-SQL穷乏BEFORE INSERT成果,请奉告我如安在T-SQL中模仿这个?

办理要领

偶然BEFORE触发器可以替代为AFTER,但在您的环境下好像不是这种环境,由于您显然必要在插入之条件供值.因此,为此目标,最靠近的成果好像是INSTEAD OF触发器,在他的评述中为 @marc_s has suggested.

但请留意,正如这两种触发范例的名称所体现的那样,BEFORE触发器和INSTEAD OF触发器之间存在基础区别.固然在这两种环境下触发器都是在没有产生由挪用触发器的语句确定的举措时执行的,可是在INSTEAD OF触发器的环境下,举措永久不该该产生.您必要完成的现实操纵必需由触发器自己完成.这与BEFORE触发器成果很是差异,个中语句老是因为执行,虽然,除非您明晰地将其回滚.

但现实上尚有其它一个题目必要办理.正如您的Oracle剧本所显现的那样,您必要转换的触发器行使SQL Server不支持的另一个成果,即FOR EACH ROW的成果. SQL Server中没有每行触发器,只有每个语句触发器.这意味着您必要始终紧记插入的数据是行集,而不只仅是单行.这增进了更多的伟大性,尽量这也许会竣事您必要思量的事项列表.

那么,这真的要办理两件事:

>改换BEFORE成果;
>替代FOR EACH ROW成果.

我实行办理这些题目如下:

CREATE TRIGGER sub_trg
ON sub1
INSTEAD OF INSERT
AS
BEGIN
  DECLARE @new_super TABLE (
    super_id int
  );
  INSERT INTO super (subtype_discriminator)
  OUTPUT INSERTED.super_id INTO @new_super (super_id)
  SELECT 'SUB1' FROM INSERTED;

  INSERT INTO sub (super_id)
  SELECT super_id FROM @new_super;
END;

这就是上面的事变道理:

>起首将插入sub1的行数添加到super中.天生的super_id值存储在姑且存储器(称为@new_super的表变量)中.
>新插入的super_ids此刻插入到sub1中.

没有什么比这更坚苦了,但只有在sub1中没有其他列而不是你在题目中指定的列时,上述内容才有用.假如尚有其他列,则上述触发器必要更伟大一些.

题目是将新的super_ids别离分派给每个插入的行.实现映射的一种要领如下:

CREATE TRIGGER sub_trg
ON sub1
INSTEAD OF INSERT
AS
BEGIN
  DECLARE @new_super TABLE (
    rownum int IDENTITY (1,
    super_id int
  );
  INSERT INTO super (subtype_discriminator)
  OUTPUT INSERTED.super_id INTO @new_super (super_id)
  SELECT 'SUB1' FROM INSERTED;

  WITH enumerated AS (
    SELECT *,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rownum
    FROM inserted
  )
  INSERT INTO sub1 (super_id,other columns)
  SELECT n.super_id,i.other columns
  FROM enumerated AS i
  INNER JOIN @new_super AS n
  ON i.rownum = n.rownum;
END;

正如您所看到的,IDENTIY(1,1)列被添加到@new_user,因此姑且插入的super_id值将其它从1开始列举.为了提供新的super_ids和新数据行之间的映射,ROW_NUMBER函数用于列举INSERTED行.因此,INSERTED荟萃中的每一行此刻都可以链接到单个super_id,从而增补到要插入sub1的完备数据行.

请留意,插入新super_ids的次序也许与它们的分派次序不匹配.我以为这不是题目.除了ID之外,天生的全部新超等行都是沟通的.以是,你必要的只是为每个新的sub1行获取一个新的super_id.

可是,假如插入到super中的逻辑更伟大,而且因为某种缘故起因必要准确记着为哪个新子行天生了哪个新的super_id,那么您也许必要思量此Stack Overflow题目中接头的映射要领:

> Using merge..output to get mapping between source.id and target.id

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读