Creating a table type param in SQL Server Stored Procedure - sql

Is it possible to declare/create the table type param(TVP) in Stored Procedure itself instead of creating the table value type separately in the schema and then using it in Stored procedure. i.e.,
create procedure proc1(
#table1 table(id int) readonly
)
as
begin
select top 1 * from sysobjects
end

From MSDN:
Table-valued parameters are based on strongly-typed table structures
that are defined by using Transact-SQL CREATE TYPE statements. You
have to create a table type and define the structure in SQL Server
before you can use table-valued parameters in your client
applications.
So it is clearly said that you can't declare TVP in stored procedure like you want - only by creating as user-defined type.

Related

sp_executesql with user defined table type not working with two databases [duplicate]

I'm using SQL Server 2008.
How can I pass Table Valued parameter to a Stored procedure across different Databases, but same server?
Should I create the same table type in both databases?
Please, give an example or a link according to the problem.
Thanks for any kind of help.
In response to this comment (if I'm correct and that using TVPs between databases isn't possible):
What choice do I have in this situation? Using XML type?
The purist approach would be to say that if both databases are working with the same data, they ought to be merged into a single database. The pragmatist realizes that this isn't always possible - but since you can obviously change both the caller and callee, maybe just use a temp table that both stored procs know about.
I don't believe it's possible - you can't reference a table type from another database, and even with identical type definitions in both DBs, a value of one type isn't assignable to the other.
You don't pass the temp table between databases. A temp table is always stored in tempdb, and is accessible to your connection, so long as the connection is open and the temp table isn't dropped.
So, you create the temp table in the caller:
CREATE TABLE #Values (ID int not null,ColA varchar(10) not null)
INSERT INTO #Values (ID,ColA)
/* Whatever you do to populate the table */
EXEC OtherDB..OtherProc
And then in the callee:
CREATE PROCEDURE OtherProc
/* No parameter passed */
AS
SELECT * from #Values
Table UDTs are only valid for stored procs within the same database.
So yes you would have to create the type on each server and reference it in the stored procs - e.g. just run the first part of this example in both DBs http://msdn.microsoft.com/en-us/library/bb510489.aspx.
If you don't need the efficency you can always use other methods - i.e. pass an xml document parameter or have the s.p. expect a temp table with the input data.
Edit: added example
create database Test1
create database Test2
go
use Test1
create type PersonalMessage as TABLE
(Message varchar(50))
go
create proc InsertPersonalMessage #Message PersonalMessage READONLY AS
select * from #Message
go
use Test2
create type PersonalMessage as TABLE
(Message varchar(50))
go
create proc InsertPersonalMessage #Message PersonalMessage READONLY AS
select * from #Message
go
use Test1
declare #mymsg PersonalMessage
insert #mymsg select 'oh noes'
exec InsertPersonalMessage #mymsg
go
use Test2
declare #mymsg2 PersonalMessage
insert #mymsg2 select 'oh noes'
exec InsertPersonalMessage #mymsg2
Disadvantage is that there are two copies of the data.
But you would be able to run the batch against each database simultaneously.
Whether this is any better than using a table table is really down to what processing/data sizes you have - btw to use a temp table from an s.p. you just access it from the s.p. code (and it fails if it doesn't exist).
Another way to solve this (though not necessarily the correct way) is to only utilize the UDT as a part of a dynamic SQL call.
USE [db1]
CREATE PROCEDURE [dbo].[sp_Db2Data_Sync]
AS
BEGIN
/*
*
* Presumably, you have some other logic here that requires this sproc to live in db1.
* Maybe it's how you get your identifier?
*
*/
DECLARE #SQL VARCHAR(MAX) = '
USE [db2]
DECLARE #db2tvp tableType
INSERT INTO #db2tvp
SELECT dataColumn1
FROM db2.dbo.tblData td
WHERE td.Id = ' + CAST(#YourIdentifierHere AS VARCHAR) '
EXEC db2.dbo.sp_BulkData_Sync #db2tvp
'
EXEC(#SQL)
END
It's definitely not a purist approach, and it doesn't work for every use case, but it is technically an option.

Is it possible to retrieve Selected Columns from Stored Procedure?

I have a stored procedure which returns a few columns from a SELECT. Now I need to grab 2 columns out of those columns in my new stored procedure and use them.. I am trying to do this using EXEC method. Is it possible to do this?
Ex : Original stored procedure:
CREATE PROCEDURE myBaseProcedure
#stId INT
AS
BEGIN
SELECT Name,
Address,
StudentId,
Grade
FROM Student
WHERE StudentId = #stId
END
New stored procedure:
CREATE PROCEDURE myNextProcedure
BEGIN
EXEC myBaseProcedure 19 -- Here I need to grab only StudentId and Name??
END
Given that you cannot dump to a temp table or table variable since the base stored procedure might sometimes add columns, there are three approaches that would do this:
You can effectively SELECT from a stored procedure using either OPENROWSET or OPENQUERY
You can use SQLCLR to create a table-valued function that executes the procedure, returns a struct of just the fields that you want, which will be the only fields that you read or "get" from the SqlDataReader.
You can use SQLCLR to create a stored procedure that executes the procedure to get a SqlDataReader, and instead of returning the SqlDataReader to SqlContext.Pipe.Send(), you would use SendResultsStart, SendResultsRow, and SendResultsEnd. You would create a SqlDataRecord of just the fields you wanted, and those would also be the only fields that you read or "get" from the SqlDataReader. While this still leaves you with a stored procedure, the filtering of the fields is done within the CLR-based proc so the output is guaranteed to be just the fields you want, regardless of how the result set structure of the base stored procedure changes. In this way you could create a local temp table to dump the results to, which would be better for JOINing to other tables. This method also allows for you to pass in a list of fields to the CLR-based stored procedure that would be parsed and used as the fields to dynamically construct the SqlDataRecord with as well as to dynamically determine which fields to get from the SqlDataReader. That would be a little more complicated but also quite a bit more flexible :).
You don't need to create a new stored procedure for this, you can integrate the stored proc call in a simple query using OpenQuery or use a temporary table.
Using OPENQUERY
SELECT Name,
Address
FROM OPENQUERY(ServerName, 'EXEC myBaseProcedure 19')
-- WHERE your_field = expected_value --> if you need to add filters
Using Temp table
Declare #MyTempTable Table (columns definitions)
Insert #MyTempTable Exec myBaseProcedure 19
Select Name,
Address
FROM #MyTempTable

cant set OUTPUT to return a table from another stored procedure

I am trying to create a stored procedure which returns a temp table to another stored procedure. However, I cannot seem to be able to set a table as an output variable. For instance:
#t table(ID int) output
as a parameters does not work. However the following does not complain:
#t int output
Is there a way to get one stored procedure to obtain a table generated by another stored proceedure? Thanks ahead of time!
The answer is No.
You could pass the name of the created table from one Stored Procedure to another and then in the second SP you can use the name to query thru the table.
Yes, you can achieve this by using a User Defined Table Type. All you need to do is
Create a User defined Table Type.
Create your first Stored Procedure to Accept a Table Type variable.
In your second procedure declare a Table Type variable, populate it with the data you want and call the first procedure by passing in the Table Type variable.
Here is a sample code.
1) Create the User Defined Table Type. Under the Programmability -- > Types -- > User Defined Table Types -- > Right click to create your table type
CREATE TYPE [schemaname].[Ttype] AS TABLE
(
EmployeeID int,
EmployeeName varchar(100),
)
GO
The above type is just an example, put in the columns that you require in it. Here Ttype is the Name of the TableType (you can name it as per your convenience)
2) Create your first stored procedure that will accept the Table type as variable so that you can use it.
CREATE PROCEDURE [schemaname].[StoredProcName]
#TableType Ttype READONLY
AS
BEGIN
-- Just an example on how to use the TableType.
INSERT INTO TableName(EmployeeId,EmployeeName)
SELECT EmployeeID,EmployeeName FROM #TableType
END
GO
The above Stored Procedure accepts a Table Type variable. The Ttype indicates that the #Tabletype variable is user defined table type. The READONLY indicates that no DML operations can be performed on the Table type parameter.
3) Now, create your second procedure that will pass the Table Type parameter to the above procedure created.
CREATE PROCEDURE [schemaname].[StoredProc2Name]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Table as Ttype
INSERT INTO #Table(EmployeeID,EmployeeName)
SELECT EmployeeID,EmployeeName FROM schemaname.Employees
EXEC [schemaname].[StoredProcName] #Table
END
GO
In the above SP, you declare a variable named #Table which is of the Table Type (Ttype). Now you populate it with the data you need and then call the first procedure by passing in the #Table variable.

Use Stored procedure like a function

I need to deal with the table name as a variable.Then I must using dynamic sql and therefore I must using Stored procedure.
But the problem that how can I use the stored procedure like a custom sql function.
e.g: select col1,(Exec sp1 param1,'tbName') from table1
Finally,I changed my design and and use dynamic SQL in one upper level.
This will be posible in sql server denali that introduces the new keywords "WITH RESULTSET".
The alternative on current sql versions is passing a temp-table to the stored procedure
Stored procedures can return scalar values through output parameters. Here's an example (from here).
Create the stored procedure like this:
CREATE PROCEDURE _4P_test
#intInput INT,
#intOutput INT OUTPUT
AS
SET #intOutput = #intInput + 1
Call it like this:
DECLARE #intResult INT
EXEC _4P_test 3, #intResult OUT
SELECT #intResult
However you should try to design your system so that you don't have to use dynamic SQL in the way you described.

Nested Create Type in Stored Procedure Declaration T-SQL

I am writing a SQL Stored Proc which takes in a single table valued parameter. Is it possible for me to create the table type in the parameter definition, for example:
CREATE PROCEDURE example (
#param (CREATE TYPE tableparameter ( column1 int, colunn2 varchar.... )) READONLY
)
No.
Databases will want the type to already exist before it can be specified as a parameter type, otherwise the database has no way to know if the data it is receiving is valid or not.