After executing this procedure, in my result set, I got only 2 fields, I could not trace out the bug. I got only Sl No and TypeofDocument in my resultset
My code:
IF OBJECT_ID('PrGetDetails') IS NOT NULL
DROP PROCEDURE PrGetDetails
GO
CREATE PROCEDURE PrGetDetails
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ReportDetails TABLE(
SlNo INT,
TypeOfDocument NVARCHAR(150),
Supplier NVARCHAR(150),
CodeNo NVARCHAR(150),
ReceivedDate Date,
ST_C DECIMAL(20,2),
ST_D DECIMAL(20,2),
EC_C DECIMAL(20,2),
EC_D DECIMAL(20,2),
HC_C DECIMAL(20,2),
HC_D DECIMAL(20,2)
);
INSERT INTO #ReportDetails (SlNo,
TypeOfDocument,
Supplier,
CodeNo,
ReceivedDate,
ST_C,
ST_D,
EC_C,
EC_D,
HC_C,
HC_D)
values
(1,'A','S1','AAJF7LSD01','2014/04/04',4362.00,0.00,87.00,0.00,44.00,0.00),
(2,'B','S2','AAJFV87LSD1','2014/04/04',2520.00,0.00,50.00,0.00,25.00,0.00),
(3,'C','S3','AK6009T001','2014/04/08',10498.00,0.00,210.00,0.00,105.00,0.00),
(4,'D','S3','AJ6009LST1','2014/04/16',45723.00,0.00,914.00,0.00,457.00,0.00),
(5,'E','S4','AAKPK8983001','2014/04/16',171.00,0.00,3.00,0.00,2.00,0.00),
(6,'F','S5','AKIPM8938P001','2014/04/16',14952.00,0.00,299.00,0.00,149.00,0.00),
(7,'G','S6','AKIPM8938P001','2014/04/16',28849.00,0.00,577.00,0.00,288.00,0.00),
(8,'','S7','AABCA7375CST042','2014/04/23',60000.00,0.00,1200.00,0.00,600.00,0.00),
(9,'','S8','AABCA7375CST042','2014/04/23',1482.00,0.00,30.00,0.00,15.00,0.00),
(10,'','S8','AABCA7375CST042','2014/04/29',250800.00,0.00,5016.00,0.00,2508.00,0.00)
SELECT * FROM #ReportDetails
END
GO
Please go to your project folder, delete the xxxx.rdl.data file. Then retrieve the data again. As I tested with your procedure, it can return all fields and records properly.
Related
I'm looking for suggestions on how to go about doing something that I am fairly certain that I should be able to do with SSIS.
I have two databases and I am updating Table B from Table A but as I do this I want to with ever successful write to Table B write some additional information to a log table back in the originating database. (See Illustration)
I'm not sure what control(s) I would use to accomplish this but suspect that it can be done inside of SSIS.
Use an OLEDB Transformation to do the UPDATE to table B, and then follow that with a Destination that writes to the log table.
After suggestions by Ivan Starostin and others on the board, I've opt'd to abandon using SSIS for doing this process and use stored procedures called from the code behind in the web page to perform this functionality. I'm including example of the insert process SP below as I'm working on the remainder but would like to close this question. Thanks to Ivan and all for your input. SSIS simply wasn't the best tool for this situation. It was much cleaner using SP as I found out.
USE [CInTracDB]
GO
/******** Object: StoredProcedure [dbo].[usp_InsertNewAssets] Script Date: 12/15/2016 3:00:00 PM *****/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Ken Carter>
-- Create date: <Dec 15, 2016>
-- Description: <Input Fields from Updates table, Insert all NEW records into CMDB.dbo.cmdb_assets, then copy record from
-- Updates to CInTracDB.dbo.Update_log, then Delete Record from Updates,
-- Return only sucesss / fail signal.
-- =============================================
CREATE PROCEDURE [dbo].[usp_InsertNewAssets](
#CAssetID as bigint,
#SubmitBy as varchar(50),
#SubmitDT as datetime,
#ApproveBy as varchar(50),
#Approved as char(10),
#ApprovedDT as datetime,
#Imported as char(10),
#ImportDT as datetime,
#AssetID as bigint,
#AssetType as int,
#AssetName as varchar(128),
#AssetShortDesc as varchar(50),
#AssetLongDesc as varchar(200),
#AssetAddNotes as varchar(254),
#AssetManuf as varchar(50),
#AssetModel as varchar(50),
#AssetTag as varchar(20),
#AssetAcqDate as datetime,
#AssetDTAssetID as varchar(20),
#AssetLocGrp as varchar(10),
#AssetLoc1 as varchar(8),
#AssetLoc2 as varchar(8),
#AssetLoc3 as varchar(8),
#AssetParent as bigint,
#AssetStatus as int,
#AssetPropType as int,
#AssetPrimUser as varchar(20),
#AssetEntered as datetime,
#AssetEnteredBy as varchar(50),
#AssetOwner as varchar(50),
#AssetCompany as varchar(10),
#AssetPriIPAddr as varchar(15),
#AssetPriMACAddr as varchar(17),
#AssetPriOS as varchar(20),
#AssetPriOSSP as varchar(20),
#AssetNotes as varchar(500),
#AssetAdminGrp as varchar(100),
#AssetSerialNum as varchar(75),
#AssetOperType as int,
#AssetOperStatus as int
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #AssetFACL as bit = 0
DECLARE #AssetStatVer as bit = 0
BEGIN
INSERT INTO CMDB.dbo.cmdb_assets (AssetType, AssetName, AssetShortDesc, AssetLongDesc, AssetAddNotes, AssetManuf,
AssetModel, AssetTag, AssetAcqDate, AssetDTAssetID, AssetLocGrp, AssetLoc1, AssetLoc2, AssetLoc3, AssetParent,
AssetStatus, AssetPropType, AssetPrimUser, AssetEntered, AssetEnteredBy, AssetOwner, AssetCompany, AssetPriIPAddr,
AssetPriMACAddr, AssetPriOS, AssetPriOSSP, AssetNotes, AssetAdminGrp, AssetSerialNum, AssetOperType,
AssetOperStatus, AssetFACL, AssetStatVer)
SELECT AssetType, AssetName, AssetShortDesc, AssetLongDesc, AssetAddNotes, AssetManuf, AssetModel, AssetTag,
AssetAcqDate, AssetDTAssetID, AssetLocGrp, AssetLoc1, AssetLoc2, AssetLoc3, AssetParent, AssetStatus, AssetPropType,
AssetPrimUser, AssetEntered, AssetEnteredBy, AssetOwner, AssetCompany, AssetPriIPAddr, AssetPriMACAddr, AssetPriOS,
AssetPriOSSP, AssetNotes, AssetAdminGrp, AssetSerialNum, AssetOperType, AssetOperStatus
FROM Updates
WHERE AssetID > 0
END
BEGIN
Insert INTO Update_log (CAssetID, SubmitBy, SubmitDT, ApproveBy, Approved, ApprovedDT, Imported, ImportDT, AssetID,
AssetType, AssetName, AssetShortDesc, AssetLongDesc, AssetAddNotes, AssetManuf, AssetModel, AssetTag, AssetAcqDate,
AssetDTAssetID, AssetLocGrp, AssetLoc1, AssetLoc2, AssetLoc3, AssetParent, AssetStatus, AssetPropType,
AssetPrimUser, AssetEntered, AssetEnteredBy, AssetOwner, AssetCompany, AssetPriIPAddr, AssetPriMACAddr, AssetPriOS,
AssetPriOSSP, AssetNotes, AssetAdminGrp, AssetSerialNum, AssetOperType, AssetOperStatus)
SELECT AssetType, AssetName, AssetShortDesc, AssetLongDesc, AssetAddNotes, AssetManuf, AssetModel, AssetTag,
AssetAcqDate, AssetDTAssetID, AssetLocGrp, AssetLoc1, AssetLoc2, AssetLoc3, AssetParent, AssetStatus, AssetPropType,
AssetPrimUser, AssetEntered, AssetEnteredBy, AssetOwner, AssetCompany, AssetPriIPAddr, AssetPriMACAddr, AssetPriOS,
AssetPriOSSP, AssetNotes, AssetAdminGrp, AssetSerialNum, AssetOperType, AssetOperStatus
FROM Updates
WHERE AssetID > 0
END
BEGIN
DELETE FROM Updates
WHERE (AssetID > 0)
END
END
GO
I have 4 tables in SQL Server: AspNetUsers, CustomerFile, CustomerOption and LastPullRecords. Application uploads the customer records from an Excel file. This Excel file is converted into DataTable and then for each row of the DataTable this stored procedure is called.
There is a trigger applied on the CustomerFile table. In this stored procedure first we check if FirstName, LastName, StreetAddress, City, State and Zip are not changed, then update only officer details other wise update all details, set the action to update ('U') and that will send the record to third party next day. Second, if that customer is not present then add it and set the action as add ('A'). After that if available then we update two other tables based on customer records.
ALTER PROC [dbo].[InsertUpdateRecords]
(
#FullName NVARCHAR(50) =NULL,
#FirstName NVARCHAR(50) =NULL,
#LastName NVARCHAR(50) =NULL,
#StreetAddress NVARCHAR(50) =NULL,
#City NVARCHAR(50) =NULL,
#State NVARCHAR(50) =NULL,
#Zip INT =NULL,
#SSN NVARCHAR(50) =NULL,
#Email NVARCHAR(150) =NULL,
#OfficerEmail NVARCHAR(50) =NULL,
#OfficerId NVARCHAR(50)=NULL,
#OfficerName NVARCHAR(50) =NULL,
#Option NVARCHAR(50) =NULL,
#DownloadedFromFTP BIT =NULL,
#LastPullDate DATETIME=NULL
)
AS
BEGIN
DECLARE #IsActive BIT
DECLARE #FileID INT
DECLARE #CompanyId INT
SET #IsActive=1
--Get Company ID based on OfficerID
Select #CompanyId=CompanyId from AspNetUsers where Email=#OfficerEmail
select top (1) #FileID=cf.fileId from CustomerFile cf inner join AspNetUsers usr on usr.Id=cf.OfficerId where cf.SSN = #SSN and usr.CompanyId=#CompanyId order by cf.FileReceivedDate, cf.FileId desc
if ((#FileID<>'') or(#FileID is not null))
Begin
-- COMPARE IF ONLY OFFICER IS CHANGED
If EXISTS(select 1 from CustomerFile where FirstName=#FirstName and LastName=#LastName and StreetAddress=#StreetAddress and City=#City and State=#State and Zip=#Zip
and FileId=#FileID
)
BEGIN
UPDATE top (1) CustomerFile SET OfficerEmail=#OfficerEmail,
OfficerName=#OfficerName,Email=#Email,
----FileModifiedDate=GETDATE(),
DownloadedFromFTP=#DownloadedFromFTP,IsActive=#IsActive,OfficerId=#OfficerId
WHERE FileId=#FileID
END
Else
BEGIN
Update top (1) CustomerFile set FullName=#FullName, FirstName=#FirstName, LastName=#LastName, StreetAddress=#StreetAddress, City=#City,State=#State,Zip=#Zip,
OfficerEmail=#OfficerEmail,OfficerName=#OfficerName,Email=#Email,
--FileReceivedDate=GETDATE(),
FileModifiedDate=GETDATE(),DownloadedFromFTP=#DownloadedFromFTP,IsActive=#IsActive,Action='U'
where FileId=#FileID
END
End
Else
BEGIN
declare #IdentityOutput table ( ID int )
INSERT INTO CustomerFile(FullName,FirstName,LastName,StreetAddress,City,State,Zip,SSN,OfficerEmail,OfficerId,OfficerName,
FileReceivedDate,DownloadedFromFTP,IsActive,Action,Email
)
output inserted.FileId into #IdentityOutput
VALUES(#FullName,#FirstName,#LastName,#StreetAddress,#City,
#State,#Zip,#SSN,#OfficerEmail,#OfficerId,#OfficerName,
GETDATE(),#DownloadedFromFTP,#IsActive,'A',#Email)
select #FileID = (select ID from #IdentityOutput)
END
---------------------------------------------------------------------------
-- Set Option
---------------------------------------------------------------------------
if ((#Option<>'') or(#Option is not null))
Begin
if exists(select 1 from CustomerOption where CustomerFileID=#FileID)
Begin
Update CustomerOption Set Option=#Option where CustomerFileID=#FileID
End
else
Begin
Insert into CustomerOption (CustomerFileID, Option) values (#FileID, #Option)
End
End
---------------------------------------------------------------------------
-- Insert Last Pull if exist
---------------------------------------------------------------------------
if ((#LastPullDate<>'') or(#LastPullDate is not null) or CONVERT(varchar(10),#LastPullDate,101)!='01/01/1900')
Begin
if((#FileID<>'') OR (#FileID<>0))
Begin
if exists (Select * from LastPullRecords where CustomerId=#FileID and CompanyId=#CompanyId)
bEGIN
Update LastPullRecords
set LastPullDate=#LastPullDate,
IsSelfPull=1,
ModifiedDateTime=getdate()
where CustomerId=#FileID and CompanyId=#CompanyId
End
ELSE
Begin
iNSERT INTO LastPullRecords
(CompanyId,CustomerId,LastPullDate,IsSelfPull,IsRTS,CreatedDateTime)
values
(#CompanyId,#FileID,#LastPullDate,1,0,getdate())
End
End
end
END
Problem is that there could be thousands of records and this query will take very long time to upload all those records. For testing i uploaded only 10K records and it took 13 minutes.
I tried to send the DataTable as parameter, defining custom User Table Type for the datatable, using while loop , then cursor but all these experiments are not making any difference.
Please suggest any optimized way to upload these records so it take less time.
I think you can choose from two options, if you want to keep using .NET for this task:
use SqlBulkCopy to copy data into intermediate tables (may be you can write insert without intermediate table), then write one command to insert all new data and second command to update all changed data.
use Table-Valued Parameters instead of SqlBulkCopy and intermediate tables (if your MSSQL not less than 2012)
Note, that SqlBulkCopy can be slower than Table-Valued Parameters for small data sets, but faster for big data sets.
I'm learning sql from a book and I'm trying to write a stored procedure but I don't believe that I'm doing it correctly. Is the following way not valid in Microsoft SQL? If not, when is it valid, if ever?
create procedure dept_count(in dept_name varchar(20), out d_count integer)
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
I get the following error
Msg 156, Level 15, State 1, Procedure wine_change, Line 1
Incorrect syntax near the keyword 'in'.
T-SQL
/*
Stored Procedure GetstudentnameInOutputVariable is modified to collect the
email address of the student with the help of the Alert Keyword
*/
CREATE PROCEDURE GetstudentnameInOutputVariable
(
#studentid INT, --Input parameter , Studentid of the student
#studentname VARCHAR (200) OUT, -- Output parameter to collect the student name
#StudentEmail VARCHAR (200)OUT -- Output Parameter to collect the student email
)
AS
BEGIN
SELECT #studentname= Firstname+' '+Lastname,
#StudentEmail=email FROM tbl_Students WHERE studentid=#studentid
END
In T-SQL stored procedures for input parameters explicit 'in' keyword is not required and for output parameters an explicit 'Output' keyword is required. The query in question can be written as:
CREATE PROCEDURE dept_count
(
-- Add input and output parameters for the stored procedure here
#dept_name varchar(20), --Input parameter
#d_count int OUTPUT -- Output parameter declared with the help of OUTPUT/OUT keyword
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Statements for procedure here
SELECT #d_count = count(*)
from instructor
where instructor.dept_name=#dept_name
END
GO
and to execute above procedure we can write as:
Declare #dept_name varchar(20), -- Declaring the variable to collect the dept_name
#d_count int -- Declaring the variable to collect the d_count
SET #dept_name = 'Test'
Execute dept_count #dept_name,#d_count output
SELECT #d_count -- "Select" Statement is used to show the output
I think it can help you:
CREATE PROCEDURE DEPT_COUNT
(
#DEPT_NAME VARCHAR(20), -- Input parameter
#D_COUNT INT OUTPUT -- Output parameter
-- Remember parameters begin with "#"
)
AS -- You miss this word in your example
BEGIN
SELECT COUNT(*)
INTO #D_COUNT -- Into a Temp Table (prefix "#")
FROM INSTRUCTOR
WHERE INSTRUCTOR.DEPT_NAME = DEPT_COUNT.DEPT_NAME
END
Then, you can call the SP like this way, for example:
DECLARE #COUNTER INT
EXEC DEPT_COUNT 'DeptName', #COUNTER OUTPUT
SELECT #COUNTER
Try this:
create procedure dept_count(#dept_name varchar(20),#d_count int)
begin
set #d_count=(select count(*)
from instructor
where instructor.dept_name=dept_count.dept_name)
Select #d_count as count
end
Or
create procedure dept_count(#dept_name varchar(20))
begin
select count(*)
from instructor
where instructor.dept_name=dept_count.dept_name
end
CREATE PROCEDURE [dbo].[USP_StudentInformation]
#S_Name VARCHAR(50)
,#S_Address VARCHAR(500)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Date VARCHAR(50)
SET #Date = GETDATE()
IF EXISTS (
SELECT *
FROM TB_StdFunction
WHERE S_Name = #S_Name
AND S_Address = #S_Address
)
BEGIN
UPDATE TB_StdFunction
SET S_Name = #S_Name
,S_Address = #S_Address
,ModifiedDate = #Date
WHERE S_Name = #S_Name
AND S_Address = #S_Address
SELECT *
FROM TB_StdFunction
END
ELSE
BEGIN
INSERT INTO TB_StdFunction (
S_Name
,S_Address
,CreatedDate
)
VALUES (
#S_Name
,#S_Address
,#date
)
SELECT *
FROM TB_StdFunction
END
END
Table Name : TB_StdFunction
S_No INT PRIMARY KEY AUTO_INCREMENT
S_Name nvarchar(50)
S_Address nvarchar(500)
CreatedDate nvarchar(50)
ModifiedDate nvarchar(50)
Create this way.
Create procedure dept_count(dept_name varchar(20),d_count integer)
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
try this:
create procedure dept_count( #dept_name varchar(20), #d_count INTEGER out)
AS
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
To Create SQL server Store procedure in SQL server management studio
Expand your database
Expand programmatically
Right-click on Stored-procedure and Select "new Stored Procedure"
Now, Write your Store procedure, for example, it can be something like below
USE DatabaseName;
GO
CREATE PROCEDURE ProcedureName
#LastName nvarchar(50),
#FirstName nvarchar(50)
AS
SET NOCOUNT ON;
//Your SQL query here, like
Select FirstName, LastName, Department
FROM HumanResources.vEmployeeDepartmentHistory
WHERE FirstName = #FirstName AND LastName = #LastName
GO
Where, DatabaseName = name of your database
ProcedureName = name of SP
InputValue = your input parameter value (#LastName and #FirstName) and type = parameter type example nvarchar(50) etc.
Source: Stored procedure in sql server (With Example)
To Execute the above stored procedure you can use sample query as below
EXECUTE ProcedureName #FirstName = N'Pilar', #LastName = N'Ackerman';
It inserted a first row successfully but it's not inserting any other row, though second row has no conflict of primary key
Code in my aspx.cs file:
outputParVal = sqlCmd.Parameters[outputParName].Value;
outparameter in stored procedure is--- "Result"
CREATE PROCEDURE [dbo].[RecruiterProfileInsert]
#CompanyId int,
#CompanyName varchar(200),
#EmailId varchar(50) ,
#Password varchar(20) ,
#ContactNumber varchar(15),
#Website varchar(50),
#CompanyProfile varchar(2000),
#IsVerified bit,
#Result Tinyint OutPut
--#CreatedDate datetime ,
--UpdatedDate datetime
AS
BEGIN
-- Insert statements for procedure here
--check whether #CompanyName already exist or not if exist then return
IF EXISTS(SELECT Top 1 * FROM RecruiterProfile WHERE #CompanyId = LTRIM(RTRIM(#CompanyId)))
BEGIN
SET #Result = 0-- Already Exists
END
ELSE
BEGIN
INSERT INTO RecruiterProfile
(
CompanyId,
CompanyName,
EmailId ,
Password ,
ContactNumber,
Website ,
CompanyProfile ,
IsVerified,
CreatedDate
)
VALUES
(
#CompanyId,
#CompanyName,
#EmailId ,
#Password,
#ContactNumber,
#Website,
#CompanyProfile,
#IsVerified,
GetDate()
)
set #Result =1
return
END
END
This is the problem:
SELECT Top 1 * FROM RecruiterProfile WHERE #CompanyId = LTRIM(RTRIM(#CompanyId))
This inherently makes no sense. You're comparing the variable to itself. Take the # sign out of one of the CompanyId references. The RTrim is unnecessary in SQL Server, and the LTrim doesn't make sense either because the later insert doesn't also LTrim so something is going to go wrong eventually.
Furthermore, inside of an EXISTS clause, TOP makes no sense unless you are using ORDER BY and doing something with the final result. Just do SELECT * inside of EXISTS clauses.
One more thing: if there is high concurrency and users could possibly try to insert the same thing at the same time, your query could still fail on a duplicate key violation.
I'm having a stored procedure which returns two result sets based on the success or failure.
SP success result set: name, id ,error,desc
SP failure result sret: error,desc
I'm using the following query to get the result of the stored procedure. It returns 0 for success and -1 for failure.
declare #ret int
DECLARE #tmp TABLE (
name char(70),
id int,
error char(2),
desc varchar(30)
)
insert into #tmp
EXEC #ret = sptest '100','King'
select #ret
select * from #tmp
If the SP is success the four field gets inserted into the temp table since the column matches.
But in case of failure the sp result set has only error and desc which does not matchs with no of columns in the temp table...
.I can't change the Sp, so I need to do some thing (not sure) in temp table to handle both failure and success.
You can't return 2 different recordsets and load the same temp table.
Neither can try and fill 2 different tables.
There are 2 options.
Modify your stored proc
All 4 columns are returned in all conditions
1st pair (name, ID) columns are NULL on error
2nd pair (error, desc) are NULL on success
If you are using SQL Server 2005 then use the TRY/CATCH to separate your success and fail code paths. The code below relies on using the new error handling to pass back the error result set via exception/RAISERROR.
Example:
CREATE PROC sptest
AS
DECLARE #errmsg varchar(2000)
BEGIN TRY
do stuff
SELECT col1, col2, col3, col4 FROM table etc
--do more stuff
END TRY
BEGIN CATCH
SELECT #errmsg = ERROR_MESSAGE()
RAISERROR ('Oops! %s', 16, 1, #errmsg)
END CATCH
GO
DECLARE #tmp TABLE ( name CHAR(70), id INT, error char(2), desc varchar(30)
BEGIN TRY
insert into #tmp
EXEC sptest '100','King'
select * from #tmp
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH
My fault!!
Was too quick in the answer.
You need only to relv on the return value, so building up the logic against it is much better.
If you still want to use the temp table, then calling the sptest twice could be a way to deal with it (not optimal though), one time to get the return value and based on it then have 2 different temp tables you are filling up (one would be with the 4 fields, the other only with 2 fields).
declare #ret int
DECLARE #tmp TABLE (name CHAR(70), id INT, error char(2), desc varchar(30))
DECLARE #tmperror TABLE (error char(2), desc varchar(30))
EXEC #ret = sptest '100','King'
IF #ret != 0
BEGIN
INSERT INTO #tmperror
EXEC sptest '100','King';
SELECT * FROM #tmperror;
END
ELSE
BEGIN
INSERT INTO #tmp
EXEC sptest '100','King';
SELECT * FROM #tmp;
END
Keep in mind that this solution is not optimal.
Try modifying your table definition so that the first two columns are nullable:
DECLARE #tmp TABLE (
name char(70) null,
id int null,
error char(2),
desc varchar(30)
)
Hope this helps,
Bill
You cannot do this with just one call. You will have to call it once, either getting the return status and then branching depending on the status to the INSERT..EXEC command that will work for the number of columns that will be returned or Call it once, assuming success, with TRY..CATCH, and then in the Catch call it again assuming that it will fail (which is how it got to the CATCH).
Even better, would be to either re-write the stored procedure so that it returns a consistent column set or to write you own stored procedure, table-valued function or query, by extracting the code from this stored procedure and adapting it to your use. This is the proper answer in SQL.