3

我有一个带有SELECT输出一行的语句的存储过程。它是这样的:

CREATE PROCEDURE [dbo].[CreateCustomer]
...

INSERT INTO Customers values(, , , ,)
SELECT CustomerID, FirstName, LastNam.....
INSERT Roles values(, , , .....

Customers这将从表中选择新存储的值。第二次插入使用 new CustomerIDRoles表中插入新行。

有没有办法只customerID从上面的 select 语句中获取而无需再次查询 CustomerID?

我试图声明一个变量并这样做:

SELECT takenCustomerID = CustomerID, FirstName, LastNam....(rest of query statement)

但我必须声明所有变量并这样做:

SELECT takenCustomerID, takenFirstName, takenLastNa... = CustomerID, FirstName, LastNam... (rest of query statement)

但是,我认为这很糟糕,因为它在服务器端浪费了大量内存。

那么,是否有一种简单的方法可以立即获取单个值,而无需在 select 语句中声明所有变量,例如可以调用 TEMP("customerID") 并获取该值的内置类似 TEMP 的变量?

另外,存储过程中可以有多个 SELECT 语句吗?我们如何从我们想要的 select 语句中获取 select 值?

出于好奇,我要求更多,因为我已经知道获得价值的方法。我只是想知道是否有更优雅的方式。

4

2 回答 2

2

除非您手动将其重定向到表,SELECT否则只会转到输出流,所以不:您不能自动访问先前选择的值。

可能只是在寻找SCOPE_IDENTITY()

declare @id int

insert ....
values (...)

set @id = SCOPE_IDENTITY()

在 DML 的一般情况下,另一个候选者是OUTPUT从句

对于基于现有选择的更一般的复合选择,表变量可能会有所帮助:

declare @foo table (id int not null, name nvarchar(100) not null) // etc

insert @foo (id, name)
select id, name from Foo where ...

select * from @foo // for output

// but we still have the @foo data available for subsequent query

... // more TSQL here

使用多个 select 语句,这完全取决于您使用的 API;但是,这里的原始 ADO.NET API 是IDataReader,它具有该NextResult()方法。多网格的典型用法是:

using(var reader = cmd.ExecuteReader()) {
    do {
        while(reader.Read()) {
          // i.e. for each row in this grid
          ...
        }
    } while (reader.NextResult()); // <== for each grid
}

while(...) {...}请注意这里和之间的区别do {...} while(...)是因为您自动从第一个网格开始,但您需要手动前进到该网格中的第一

于 2012-07-30T06:38:58.240 回答
2

访问插入的值

很简单。使用该OUTPUT子句返回您刚刚创建的值。

DECLARE @Customers TABLE (
   CustomerID uniqueidentifier,
   FirstName varchar(100),
   LastName varchar(100)
);

INSERT dbo.Customers 
OUTPUT Inserted.*
INTO @Customers
SELECT newsequentialid(), @FirstName, @LastName, ...;
-- now you have all the values of the new row in the `@Customers` table variable.

然后你可以这样做:

INSERT dbo.Roles
SELECT
   CustomerID,
   @OtherValue,
   @AnotherValue,
   AnyotherColumnFrom@Customers
FROM @Customers;

如果您不再使用插入的 Customer 行中的值,您甚至可以取消表变量,直接将 OUTPUT 输入到 Roles 表中,假设进入该表的所有值都来自变量。

OUTPUT子句允许使用特殊的 meta-table 访问插入的值Inserted。但是,您也可以将变量和表达式与常量一起使用。

使用这种方法的好处是您可以一次处理许多插入的行。如果您只插入一行,则只需要后面的CustomerID,并且需要多次使用它,然后改为这样做:

DECLARE @CustomerID uniqueidentifier = newsequentialid();
INSERT @Customer VALUES (@CustomerID, ...);
INSERT @Roles VALUES (..., @CustomerID ...);

通过提前创建 GUID,您无需将其从表中取回。顺便说一句,newsequentialid()它可能优于newid()聚集索引(这可能是真的),因为您将避免newid可能导致的页面拆分。

返回多个结果集

这总是可能的。无论您使用什么方法进行查询,都会有一种方法可以将您的数据访问对象推进到下一个记录集。如果您使用的是DataReader然后查看该NextResult方法。在经典 ADO 中,记录集有一个NextRecordset方法。

于 2012-07-30T06:48:40.943 回答