AS MERGE的存储过程没有返回任何内容?

时间:2018-02-21 15:17:20

标签: sql sql-server

编辑:顺序发票编号是多个国家/地区的法律。

编辑:我的变量命名不佳表明我想将生成的ID用作关键字。不是这种情况。应该坚持'invoiceNumber'。

我和https://stackoverflow.com/a/24196374/1980516

提出了完全相同的问题

但是,由于提出的解决方案引发了语法错误,我已将其改编为使用游标。

首先,存储过程为给定的Business + Year组合生成新的Nr:

CREATE PROCEDURE PROC_NextInvoiceNumber @businessId INT, @year INT, @Nr NVARCHAR(MAX) OUTPUT 
AS MERGE INTO InvoiceNextNumbers ini
    USING (VALUES (@businessId, @year)) Incoming(BusinessId, Year)
        ON Incoming.BusinessId = ini.BusinessId AND Incoming.Year = ini.Year
    WHEN MATCHED THEN UPDATE SET ini.Nr = ini.Nr + 1
    WHEN NOT MATCHED BY TARGET THEN INSERT (BusinessId, Year, Nr) 
VALUES(@businessId, @year, 1)

OUTPUT INSERTED.Nr;

然后,使用该存储过程,我创建了一个INSTEAD OF INSERT触发器:

CREATE TRIGGER TRIG_GenerateInvoiceNumber ON Invoices INSTEAD OF INSERT
AS 
  BEGIN

    DECLARE @BusinessId INT
    DECLARE @InvoiceId INT
    DECLARE @BillingDate DATETIME2(7)

    -- Cursors are expensive, but I don't see any other way to call the stored procedure per row
    -- Mitigating factor: Mostly, we're only inserting one Invoice at a time
    DECLARE InsertCursor CURSOR FAST_FORWARD FOR
    SELECT BusinessId, Id, BillingDate FROM INSERTED

    OPEN InsertCursor
    FETCH NEXT FROM InsertCursor
    INTO @BusinessId, @InvoiceId, @BillingDate
    WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE @year INT
        SET @year = year(@BillingDate)

        DECLARE @Number NVARCHAR(MAX)
        EXEC PROC_NextInvoiceNumber @BusinessId, @year, @Number OUTPUT
        -- SET @Number = 'this works'

        INSERT INTO Invoices (BusinessId, Id, BillingDate, Number) 
            VALUES (@BusinessId, @InvoiceId, @BillingDate, @Number)

        FETCH NEXT FROM InsertCursor
        INTO @BusinessId, @InvoiceId, @BillingDate
    END
    CLOSE InsertCursor
    DEALLOCATE InsertCursor

    END

如果我取消注释SET @Number = 'this works',那么在我的数据库中,在Invoice.Number中成功设置了确切的字符串('this works')。

不知怎的,我的OUTPUT参数没有设置,我无法弄清楚为什么不能..有人能说清楚这个吗?

编辑更新以回应评论(谢谢):

  • 我有一个Invoice的复合键(BusinessId,Id)。所需的最终结果是一个唯一的Invoice Identifier 形式为'20180001'的数字,它是businessId中的连续数字。因此,业务1的发票号为20180001,20180002,20180003,业务2 的发票号为20180001,20180002,20180003。(但不同的复合主键)

  • 我也不想要那个光标,但我在框架内没有看到其他方式,正如我上面提到的问题所示。

  • PROC_NextInvoiceNumber的手动调用,现有业务ID和年份返回NULL。

  • 如果我尝试在PROC_NextInvoiceNumber中设置Id,如果我在MERGE中设置了A MERGE statement must be terminated by a semi-colon (;).,或者如果我设置在MERGE之外,我会The multi-part identifier "INSERTED.Nr" could not be bound.

1 个答案:

答案 0 :(得分:2)

永远不会设置您的OUTPUT参数。您正在使用OUTPUT clause of the MERGE语句来创建结果集。这与为参数赋值无关。

<p:treeTable nodeVar="node" ...>
  ...
  <p:column style="width:32px">
    <p:rowEditor styleClass="rowKey-#{node.rowKey}"/>
  </p:column>
</p:treeTable>

更改代码以实际为@Nr分配内容:

document.querySelector(".rowKey-"+ rowKey +" .ui-row-editor-pencil span").click();

典型的方法是使用OUTPUT子句将所需的值存储到表变量中,然后将值赋给所需的输出*变量:

MERGE INTO..
USING ... ON ...
WHEN MATCHED THEN UPDATE ...
WHEN NOT MATCHED BY TARGET THEN INSERT ...
OUTPUT INSERTED.Nr;  /* <-- HERE this is the OUTPUT *clause*  */