web-dev-qa-db-ja.com

SQL Serverストアドプロシージャがテーブルを返す

2つのパラメーターを受け取るストアドプロシージャがあります。 Server Management Studioで正常に実行できます。期待どおりの結果が表示されます。ただし、戻り値も返します。

この行を追加しました、

 SELECT 'Return Value' = @return_value

このストアドプロシージャは、MATLABからこのストアドプロシージャを呼び出しているときに返される値ではなく、結果に表示されるテーブルを返しますが、返すものはすべてtrueまたはfalseです。

ストアドプロシージャで何を返すかを指定する必要がありますか?もしそうなら、4列のテーブルを指定するにはどうすればよいですか(varchar(10)、float、float、float)?

33
mHelpMe

プロシージャは、テーブル自体を返すことはできません。ただし、プロシージャ内のテーブルから選択して、次のようにテーブル(またはテーブル変数)に送ることができます。

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
67
t-clausen.dk

テーブルを返し、クエリで使用できる関数を作成することを検討してください。

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

関数とプロシージャの主な違いは、関数がテーブルを変更しないことです。値のみを返します。

この例では、クエリを作成して、指定されたテーブル内のNULLまたは空ではないすべての列のカウントを取得しています。

おそらくこれをきれいにする多くの方法があります。しかし、それは機能をよく示しています。

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

次に、関数を実行します

SELECT * FROM usp_listFields('Employees')

次のような行を生成します。

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
6
Algonaut

一貫性を確保し、コードを簡素化するために、テーブルタイプを使用してこれを頻繁に行います。技術的に「テーブル」を返すことはできませんが、結果セットを返すことができ、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
5
rainabba

結果セットと戻り値の両方が必要な場合は、戻り値の代わりにoutパラメーターを使用できます

CREATE PROCEDURE proc_name 
@param int out
AS
BEGIN
    SET @param = value
SELECT ... FROM [Table] WHERE Condition
END
GO
3
SpaceghostAli

ストアドプロシージャによって返されるステータス値は、INTデータ型のみです。 RETURNステートメントで他のデータ型を返すことはできません。

から レッスン2:ストアドプロシージャの設計

すべてのストアドプロシージャは、実行ステータス値またはリターンコードとして知られるinteger値を返すことができます。

それでもSPからテーブルを返す必要がある場合は、SP内のSELECTから返されたレコードセットを処理するか、XMLデータ型を渡すOUTPUT変数に関連付ける必要があります。

HTH、

ジョン

3
John Eisbrener

私は同様の状況にあり、プロシージャ内で一時テーブルを使用して解決しました。元のストアドプロシージャによって同じフィールドが返されました。

CREATE PROCEDURE mynewstoredprocedure
AS 
BEGIN

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

select field1, field2 from temptable

-- (mystoredprocedure returns field1, field2)

END
2
Cassio Veras
create procedure PSaleCForms
as
begin
declare 
@b varchar(9),
@c nvarchar(500),
@q nvarchar(max)
declare @T table(FY nvarchar(9),Qtr int,title nvarchar    (max),invoicenumber     nvarchar(max),invoicedate datetime,sp decimal    18,2),grandtotal decimal(18,2))
declare @data cursor
set @data= Cursor
forward_only static
for 
select x.DBTitle,y.CurrentFinancialYear from [Accounts     Manager].dbo.DBManager x inner join [Accounts Manager].dbo.Accounts y on        y.DBID=x.DBID where x.cfy=1
open @data
fetch next from @data
into @c,@b
while @@FETCH_STATUS=0
begin
set @q=N'Select '''+@b+''' [fy], case cast(month(i.invoicedate)/3.1 as int)     when 0 then 4 else cast(month(i.invoicedate)/3.1 as int) end [Qtr],     l.title,i.invoicenumber,i.invoicedate,i.sp,i.grandtotal from     ['+@c+'].dbo.invoicemain i inner join  ['+@c+'].dbo.ledgermain l on     l.ledgerid=i.ledgerid where (sp=0 or stocktype=''x'') and invoicetype=''DS'''

@T execに挿入[master] .dbo.sp_executesql @q @dataから@cにフェッチする@ c、@ b end close @data deallocate @data select * from @T return end

0
Rohit