SQL Server存储过程返回一个表

mHe*_*pMe 35 sql sql-server matlab stored-procedures

我有一个存储过程,它接受两个参数.我可以在Server Management Studio中成功执行它.它向我展示了我期望的结果.但是它也会返回一个返回值.

它增加了这条线,

 SELECT 'Return Value' = @return_value
Run Code Online (Sandbox Code Playgroud)

我希望存储过程返回它在结果中显示的表而不是返回值,因为我从MATLAB调用此存储过程并且它返回的全部为true或false.

我是否需要在我的存储过程中指定它应该返回什么?如果是这样,我如何指定一个包含4列的表(varchar(10),float,float,float)?

t-c*_*.dk 70

过程不能返回表.但是,您可以从过程中的表中进行选择,并将其指向表(或表变量),如下所示:

create procedure p_x
as
begin
declare @t table(col1 varchar(10), col2 float, col3 float, col4 float)
insert @t values('a', 1,1,1)
insert @t values('b', 2,2,2)

select * from @t
end
go

declare @t table(col1 varchar(10), col2 float, col3 float, col4 float)
insert @t
exec p_x

select * from @t
Run Code Online (Sandbox Code Playgroud)

  • 我建议也看一下[**this**](http://stackoverflow.com/questions/5604927/how-to-return-a-table-from-stored-procedure)解决方案.人们会直觉地认为它不会起作用,但确实如此,这使得它成为最简单的方法. (7认同)
  • 重要的是要注意`INSERT-EXEC`**不能嵌套**.这种方法也可能导致"ROLLBACK TRANSACTION"出现问题.见[this source](http://www.sommarskog.se/share_data.html#INSERTEXEC). (4认同)

Alg*_*aut 6

考虑创建一个可以返回表并在查询中使用的函数.

https://msdn.microsoft.com/en-us/library/ms186755.aspx

函数和过程之间的主要区别在于函数不会对任何表进行任何更改.它只返回一个值.

在这个例子中,我正在创建一个查询,以便给出给定表中非空或空的所有列的计数.

有很多方法可以清理它.但它很好地说明了一个功能.

USE Northwind

CREATE FUNCTION usp_listFields(@schema VARCHAR(50), @table VARCHAR(50))
RETURNS @query TABLE (
    FieldName VARCHAR(255)
    )
BEGIN
    INSERT @query
    SELECT
        'SELECT ''' + @table+'~'+RTRIM(COLUMN_NAME)+'~''+CONVERT(VARCHAR, COUNT(*)) '+
    'FROM '+@schema+'.'+@table+' '+
          ' WHERE isnull("'+RTRIM(COLUMN_NAME)+'",'''')<>'''' UNION'
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @table and TABLE_SCHEMA = @schema
    RETURN
END
Run Code Online (Sandbox Code Playgroud)

然后执行该功能

SELECT * FROM usp_listFields('Employees')
Run Code Online (Sandbox Code Playgroud)

产生许多行,如:

SELECT 'Employees~EmployeeID~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees  WHERE isnull("EmployeeID",'')<>'' UNION
SELECT 'Employees~LastName~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees  WHERE isnull("LastName",'')<>'' UNION
SELECT 'Employees~FirstName~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees  WHERE isnull("FirstName",'')<>'' UNION
Run Code Online (Sandbox Code Playgroud)


rai*_*bba 6

我经常使用表类型来确保更高的一致性并简化代码.您不能在技术上返回"表",但是您可以返回结果集并使用INSERT INTO .. EXEC ...语法,您可以清楚地调用PROC并将结果存储到表类型中.在下面的例子中,我实际上是将表传递给PROC以及另一个我需要添加逻辑的参数,然后我实际上"返回一个表",然后可以将其作为表变量使用.

/****** Check if my table type and/or proc exists and drop them ******/
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'returnTableTypeData')
DROP PROCEDURE returnTableTypeData
GO
IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = 'myTableType')
DROP TYPE myTableType
GO

/****** Create the type that I'll pass into the proc and return from it ******/
CREATE TYPE [dbo].[myTableType] AS TABLE(
    [someInt] [int] NULL,
    [somenVarChar] [nvarchar](100) NULL
)
GO

CREATE PROC returnTableTypeData
    @someInputInt INT,
    @myInputTable myTableType READONLY --Must be readonly because
AS
BEGIN

    --Return the subset of data consistent with the type
    SELECT
        *
    FROM
        @myInputTable
    WHERE
        someInt < @someInputInt

END
GO


DECLARE @myInputTableOrig myTableType
DECLARE @myUpdatedTable myTableType

INSERT INTO @myInputTableOrig ( someInt,somenVarChar )
VALUES ( 0, N'Value 0' ), ( 1, N'Value 1' ), ( 2, N'Value 2' )

INSERT INTO @myUpdatedTable EXEC returnTableTypeData @someInputInt=1, @myInputTable=@myInputTableOrig

SELECT * FROM @myUpdatedTable


DROP PROCEDURE returnTableTypeData
GO
DROP TYPE myTableType
GO
Run Code Online (Sandbox Code Playgroud)


小智 5

我遇到了类似的情况,并通过在过程中使用临时表来解决,原始存储过程返回相同的字段:

CREATE PROCEDURE mynewstoredprocedure
AS 
BEGIN

INSERT INTO temptable (field1, field2)
EXEC mystoredprocedure @param1, @param2

select field1, field2 from temptable

-- (mystoredprocedure returns field1, field2)

END
Run Code Online (Sandbox Code Playgroud)