【问题标题】:Inline SQL function which sometimes must update database有时必须更新数据库的内联 SQL 函数
【发布时间】:2014-09-03 15:43:26
【问题描述】:

是否可以创建一个函数/过程,可以在这样的 SQL 语句中使用:

INSERT INTO Journal(ProductID,Quantity) VALUES(LookupOrCreateProduct('12345678'),5)

LookupOrCreateProduct 应按字符串(条形码)查找产品表,并且:
* 如果找到条形码 - 返回产品 ID
* 如果未找到条形码 - 在 Products 表中使用新条形码创建新记录并返回其 ID

我探索了 SQL Server 函数,但它们不允许 INSERTs 或函数体内的任何其他数据库修改。存储过程可以返回值,但它们只能是int 类型。我的 ID 列是bigint。另一种选择是使用输出参数,但我不清楚如何在 SQL 语句中内联它。谢谢。

【问题讨论】:

  • 设置 Bigint 数据类型的输出参数并从存储过程中返回并保存到变量中,然后将其用于插入查询...
  • 你不能用函数来做到这一点。 And you should use an OUTPUT parameter, not a RETURN value。 RETURN 值用于错误/状态代码,而不用于数据;主要原因之一正是您所发现的:它们仅对整数有用。

标签: sql sql-server inline-functions


【解决方案1】:
CREATE PROCEDURE LookupOrCreateProduct 
   @BarCode    VARCHAR(100),
   @ProductID  BIGINT OUTPUT
AS
BEGIN
   SET NOCOUNT ON;


       SELECT TOP 1 @ProductID = ProductID
       FROM dbo.Products 
       WHERE BarCode = @BarCode

   IF(@ProductID IS NULL)
    BEGIN
      INSERT INTO dbo.Products(Barcode)
      VALUES (@BarCode)

      SET @ProductID = SCOPE_IDENTITY();
    END   

END

【讨论】:

  • 为什么要检查IF EXISTS?即使 BarCode 被索引,这也是一种浪费的额外检查。 SELECT @ProductID = ... IF @ProductID IS NULL 然后插入。
  • @AaronBertrand 当然这样更有意义,谢谢你的指点 :)
【解决方案2】:

我认为你能做的最好的就是在存储过程中输出参数:

declare @product_id int;

begin transaction;

exec dbo.LookupOrCreateProduct '12345678', @product_id out;

insert into journal (productId, quantity) values (@product_id, 5);

commit transaction;

【讨论】:

    猜你喜欢
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2019-12-09
    相关资源
    最近更新 更多