【问题标题】:SQL Server : scalar function returns nothing, but it should return INTSQL Server:标量函数不返回任何内容,但它应该返回 INT
【发布时间】:2014-09-01 17:57:14
【问题描述】:

这是我的功能:

CREATE FUNCTION fu_order_customer_adress (@customer_ID INT)
RETURNS INT AS
    BEGIN
        RETURN (
            SELECT c.adress_ID FROM customers AS c
            JOIN orders AS o ON (c.customer_ID = o.customer_ID)
            WHERE c.customer_ID = @customer_ID)
    END

用于表orders的AFTER INSERT触发器,其结构如下(不含不重要的列):

orders (order_ID INT, customer_ID INT, employee_ID)

order_ID是主键,其他列是外键。

触发器如下所示:

CREATE TRIGGER tr_orders_insert ON orders
AFTER INSERT 
AS
BEGIN
    DECLARE @order_ID INT = (SELECT order_ID FROM INSERTED);
    DECLARE @customer_ID INT = (SELECT customer_ID FROM INSERTED);

    UPDATE orders
    SET adress_ID = (SELECT dbo.fu_order_customer_adress(@customer_ID))
    WHERE order_ID = @order_ID;
END

以下插入已编号,以便稍后轻松指出。

(1) 这适用于具有不同 customer_ID 的插入:

INSERT INTO orders(customer_ID, employee_ID) 
VALUES (1, 1)

INSERT INTO orders(customer_ID, employee_ID) 
VALUES (2, 2)

(2) 但是当插入已经使用customer_ID的订单时,插入会以错误结束:

INSERT INTO orders(customer_ID, employee_ID) 
VALUES (1, 2)

我发现这是由触发器中使用的函数引起的,因为在这种情况下它什么也不返回。

我尝试将函数中使用的SELECT function 和SELECT 放入触发器中:

CREATE TRIGGER tr_orders_insert ON objednavka
AFTER INSERT 
AS
BEGIN
    DECLARE @order_ID INT = (SELECT order_ID FROM INSERTED);
    DECLARE @customer_ID INT = (SELECT customer_ID FROM INSERTED);

    SELECT c.adress_ID 
    FROM customers AS c
    JOIN orders AS o ON (c.customer_ID = o.customer_ID)
    WHERE c.customer_ID = @customer_ID)

    SELECT dbo.fu_order_customer_adress(@customer_ID)

    UPDATE orders
    SET adress_ID = (SELECT dbo.fu_order_customer_adress(@customer_ID))
    WHERE order_ID = @order_ID;
END

In (1) 都是SELECT 结果相同。

In (2) 是SELECT 结果正常,但SELECT function 什么也不返回。

我不明白出了什么问题...感谢您的帮助!

【问题讨论】:

    标签: sql sql-server function triggers insert


    【解决方案1】:

    对于你这个简单的触发器,我认为你不需要这个性能杀手标量函数,你可以简单地执行以下操作,而无需使用任何标量函数,只需将表与插入的表连接起来。

    此外,您的触发器中的逻辑存在重大问题,它仅适用于单个插入,如果您的 Orders 表中有多个插入,它将失败。一种更安全、性能更高效的方法是......

    CREATE TRIGGER tr_orders_insert ON orders
    AFTER INSERT AS
    BEGIN
      SET NOCOUNT ON;
    
        UPDATE O
           SET O.adress_ID = C.adress_ID
        FROM orders O 
        INNER JOIN inserted  AS I   ON O.order_ID    = I.order_ID 
        INNER JOIN customers AS c   ON C.customer_ID = I.customer_ID         
    
    END
    

    【讨论】:

    • 1) 我也在为这个数据库编写信息系统应用程序,其中没有任何多个插入...但是你当然是对的,这不安全。 2) 我会用inserted 表试试JOIN,谢谢。但是为什么我的函数表现得像我描述的那样?
    猜你喜欢
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多