J'ai une procédure stockée qui prend deux paramètres. Je peux l'exécuter avec succès dans Server Management Studio. Il me montre les résultats qui sont comme je l’attendais. Cependant, il renvoie également une valeur de retour.
Il a ajouté cette ligne,
SELECT 'Return Value' = @return_value
Je voudrais que la procédure stockée retourne la table, elle me montre dans les résultats, pas la valeur de retour, car j'appelle cette procédure stockée à partir de MATLAB et tout ce qu'elle renvoie est true ou false.
Dois-je spécifier dans ma procédure stockée ce qu'elle doit renvoyer? Si oui, comment spécifier un tableau de 4 colonnes (varchar (10), float, float, float)?
Une procédure ne peut pas retourner une table en tant que telle. Cependant, vous pouvez sélectionner une table dans une procédure et la diriger vers une table (ou une variable de table) comme ceci:
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
Envisagez de créer une fonction pouvant renvoyer une table et être utilisée dans une requête.
https://msdn.Microsoft.com/en-us/library/ms186755.aspx
La principale différence entre une fonction et une procédure est qu'une fonction ne modifie aucune table. Il ne retourne qu'une valeur.
Dans cet exemple, je crée une requête pour me donner le nombre de toutes les colonnes d'une table donnée qui ne sont ni nulles ni vides.
Il y a probablement plusieurs façons de nettoyer cela. Mais cela illustre bien une fonction.
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
Puis en exécutant la fonction avec
SELECT * FROM usp_listFields('Employees')
produit un nombre de lignes comme:
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
Je le fais fréquemment en utilisant des types de table pour assurer plus de cohérence et simplifier le code. Techniquement, vous ne pouvez pas renvoyer "une table", mais vous pouvez renvoyer un jeu de résultats. En utilisant la syntaxe INSERT INTO .. EXEC ...
, vous pouvez clairement appeler un PROC et stocker les résultats dans un type de table. Dans l'exemple suivant, je passe en réalité une table dans un PROC avec un autre paramètre dont j'ai besoin pour ajouter une logique, puis je "retourne une table" et je peux ensuite l'utiliser avec une variable de table.
/****** 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
Vous pouvez utiliser un paramètre out au lieu de la valeur renvoyée si vous souhaitez un ensemble de résultats et une valeur renvoyée.
CREATE PROCEDURE proc_name
@param int out
AS
BEGIN
SET @param = value
SELECT ... FROM [Table] WHERE Condition
END
GO
J'ai eu une situation similaire et résolu en utilisant une table temporaire à l'intérieur de la procédure, avec les mêmes champs retournés par la procédure stockée d'origine:
CREATE PROCEDURE mynewstoredprocedure
AS
BEGIN
INSERT INTO temptable (field1, field2)
EXEC mystoredprocedure @param1, @param2
select field1, field2 from temptable
-- (mystoredprocedure returns field1, field2)
END
La valeur de statut renvoyée par une procédure stockée ne peut être qu'un type de données INT. Vous ne pouvez pas renvoyer d'autres types de données dans l'instruction RETURN.
De Leçon 2: Conception de procédures stockées :
Chaque procédure stockée peut renvoyer une valeur integer connue sous le nom de valeur du statut d'exécution ou code de retour.
Si vous souhaitez toujours obtenir une table renvoyée du SP, vous devrez soit utiliser le jeu d'enregistrements renvoyé à partir d'un SELECT dans SP, soit l'associer à une variable OUTPUT qui transmet un type de données XML.
HTH,
John
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'''
insérer dans @T exec [maître] .dbo.sp_executesql @q extraire ensuite de @data dans @ c, @ b fin fermer @data traiter. @louer. sélectionnez * de @T return end