how to use openrowset to execute a stored procedure with parameters - sql-server-2008

I'm creating a stored procedure which gets some parameters and in turn these parameters are sent to another stored procedure which I'm calling from openrowset but I'm getting some syntax errors.
CREATE PROCEDURE UpdatePrevFYConfigData
-- Add the parameters for the stored procedure here
#startDate datetime,
#endDate datetime,
#productGroup varchar(8000) = 'All',
#projectType varchar(500) = 'All',
#businessUnit nvarchar(50) = 'All',
#developmentLocation nvarchar(100) = 'All'
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #start varchar(50)
declare #end varchar(50)
set #start = cast(#startDate as varchar(40))
set #end = cast(#endDate as varchar(40))
-- Insert statements for procedure here
select round(avg(a.DeviationDeadline),2) as DeviationDeadline,
round(avg(a.DeviationDefinition),2) as DeviationDefinition,
round(avg(a.DeviationRDCosts),2) as DeviationRDCosts,
round(avg(a.FunctionsAdded) + avg(a.FunctionsDeleted),2) as NotRealizedFuncs,
round(avg(a.DeviationPM2000Aufwand),2) as DeviationPM200Aufwand,
round(avg(b.Defect),2) as Defect
into #tempTable
from openrowset('SQLNCLI',
'Server=.\sqlexpress;Trusted_Connection=yes;',
'SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.SelectScorecardGraphData
'''+#start+''',
'''+#end+''',
'''+#productGroup+''',
'''+#projectType+''',
''1'',
''0'',
''All'',
''Current'',
'''+#businessUnit+''',
'''+#developmentLocation+'''
') as a,
openrowset('SQLNCLI', 'Server=.\sqlexpress;Trusted_Connection=yes;', 'SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.GetSPCDefectDistributionData
'''+cast(#startDate as varchar(40))+''',
'''+cast(#endDate as varchar(40))+''',
''Defect'',
'''+#projectType+''',
'''+#productGroup+''',
'''+#businessUnit+''',
'''+#developmentLocation+'''') as b
update dbo.EA_ProcessScorecard_Config_Tbl
set EPC_Deviation = case EPC_Metric
when 'PM200' then (select DeviationDefinition from #tempTable)
when 'PM300' then (select DeviationDeadline from #tempTable)
when 'Cost' then (select DeviationRDCosts from #tempTable)
when 'PM150' then (select DeviationPM200Aufwand from #tempTable)
when 'Defect' then (select Defect from #tempTable)
when 'Funcs' then (select NotRealizedFuncs from #tempTable)
END
where EPC_Description = 'PrevFY' and EPC_FYYear = '0'
drop table #tempTable
END
GO
I'm not able to create it and I get the error message:
Msg 102, Level 15, State 1, Procedure UpdatePrevFYConfigData,
Line 38 Incorrect syntax near '+'.
... but if I use hard coded values for the parameters it works!!
Please help!

Both OPENROWSET and OPENDATASOURCE should be used only for accessing external data for, let's say, quick and dirty solutions, or when it is not possible to configure a permanent linked server. These functions do not provide all of the functionality available from a linked server.
The arguments of OPENROWSET and OPENDATASOURCE do not support variables. They have to be specified as string-literal. If variables need to be passed in as arguments to these functions, a query string containing these variables can be constructed dynamically and executed using the EXEC statement.
Similar to (not syntax checked)
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = 'SELECT *
FROM OPENROWSET(''SQLNCLI'',''server=.\sqlexpress;Trusted_Connection=yes'',''SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.SelectScorecardGraphData ''''' + cast(#param1 as varchar(10)) + ''''',''' + cast(#param2 as varchar(n)) ''')'
EXEC #sqlCommand
And so on...
Hope that helps. Kind regards,
Stefan

-- FOR USING OPENROWSETS
EXEC sp_configure 'Ad Hoc Distributed Queries'
,1
RECONFIGURE
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'INSERT INTO #TABLESIZESYEAR SELECT NULL AS [TABLE NAME], * FROM OPENROWSET
(''SQLOLEDB'',''Server=(local);TRUSTED_CONNECTION=YES;'',''set fmtonly off EXEC one.[dbo].[InvestigateDataGrowthByYearAndClient] #pDATECOLUMN =' + #YEARCOLUMN + ' ,
#pTABLENAME = ' + #TABLENAME + ' WITH RESULT SETS(
([YEAR NAME] NVARCHAR(5) NULL
, [NUMBER OF ROWS] CHAR(11)
, [RESERVED SPACE] VARCHAR(18)
, [DATA SPACE] VARCHAR(18)
, [INDEX SIZE] VARCHAR(18)
, [UNUSED SPACE] VARCHAR(18) )
)
;'') '
DECLARE #ParmDefinition NVARCHAR(500) = '#pDATECOLUMN NVARCHAR(20)
,#YEARCOLUMN NVARCHAR(20)
,#pTABLENAME NVARCHAR(60)';
EXECUTE sp_executesql #sql
,#ParmDefinition
,#YEARCOLUMN = #YEARCOLUMN
,#pDATECOLUMN = #YEARCOLUMN
,#pTABLENAME = #TABLENAME

Related

Running sql script in sqlcmd is cutting part of my html code in file result

I create a Script sql-server that returns two html code from two different views that I created. The problem is that, when I'm running the .sql file (scrip) in sqlcmd, the html result in the file output is incomplete (obs. If I execute in management studio, the result in html is complete).
I have no idea how to proceed. I think in Oracle set long is used, but I don't know in Microsoft SQL Server.
--CODE IN SQLCMD
--SQLCMD -S LOCALHOST\SQLEXPRESS -i C:\checklist_sql\check_sql\checklist.sql -o C:\checklist_sql\lib\resultado.html
SET NOCOUNT ON;
---------ROCEDUR TO HTML----
GO
create PROCEDURE [dbo].[SqlTableToHtml] (
#TABLENAME NVARCHAR(500),
#OUTPUT NVARCHAR(MAX) OUTPUT,
#TBL_STYLE NVARCHAR(1024) = '',
#TD_STYLE NVARCHAR(1024) = '',
#HDR_STYLE NVARCHAR(1024) = '')
AS
-- Description
-- Stored Procedure to take an arbitraty temporary table and return
-- the equivalent HTML string .
-- #exec_str stores the dynamic SQL Query
-- #ParmDefinition stores the parameter definition for the dynamic SQL
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--We need to use Dynamic SQL at this point so we can expand the input table name parameter
SET #exec_str= N'
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--Make a copy of the original table adding an indexing columnWe need to add an index column to the table to facilitate sorting so we can maintain the
--original table order as we iterate through adding HTML tags to the table fields.
--New column called CustColHTML_ID (unlikely to be used by someone else!)
--
select CustColHTML_ID=0,* INTO #CustomTable2HTML FROM ' + #TABLENAME + '
--Now alter the table to add the auto-incrementing index. This will facilitate row finding
DECLARE #COUNTER INT
SET #COUNTER=0
UPDATE #CustomTable2HTML SET #COUNTER = CustColHTML_ID=#COUNTER+1
-- #HTMLROWS will store all the rows in HTML format
-- #ROW will store each HTML row as fields on each row are iterated through
-- using dymamic SQL and a cursor
-- #FIELDS will store the header row for the HTML Table
DECLARE #HTMLROWS NVARCHAR(MAX) DECLARE #FIELDS NVARCHAR(MAX)
SET #HTMLROWS='''' DECLARE #ROW NVARCHAR(MAX)
-- Create the first HTML row for the table (the table header). Ignore our indexing column!
SET #FIELDS=''<tr>''
SELECT #FIELDS=COALESCE(#FIELDS, '' '','''')+''<th ' + #HDR_STYLE + '>'' + name + ''</th>''
FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
SET #FIELDS=#FIELDS + ''</tr>''
-- #ColumnName stores the column name as found by the table cursor
-- #maxrows is a count of the rows in the table, and #rownum is for marking the
-- ''current'' row whilst processing
DECLARE #ColumnName NVARCHAR(500)
DECLARE #maxrows INT
DECLARE #rownum INT
--Find row count of our temporary table
SELECT #maxrows=count(*) FROM #CustomTable2HTML
--Create a cursor which will look through all the column names specified in the temporary table
--but exclude the index column we added (CustColHTML_ID)
DECLARE col CURSOR FOR
SELECT name FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
ORDER BY column_id ASC
--For each row, generate dymanic SQL which requests the each column name in turn by
--iterating through a cursor
SET #rowNum=0
SET #ParmDefinition=N''#ROWOUT NVARCHAR(MAX) OUTPUT,#rowNum_IN INT''
While #rowNum < #maxrows
BEGIN
SET #HTMLROWS=#HTMLROWS + ''<tr>''
SET #rowNum=#rowNum +1
OPEN col
FETCH NEXT FROM col INTO #ColumnName
WHILE ##FETCH_STATUS=0
BEGIN
--Get nth row from table
SET #exec_str=''SELECT #ROWOUT=(select COALESCE(['' + #ColumnName + ''], '''''''') AS ['' + #ColumnName + ''] from #CustomTable2HTML where CustColHTML_ID=#rowNum_IN)''
EXEC sp_executesql
#exec_str,
#ParmDefinition,
#ROWOUT=#ROW OUTPUT,
#rowNum_IN=#rownum
SET #HTMLROWS =#HTMLROWS + ''<td ' + #TD_STYLE + '>'' + #ROW + ''</td>''
FETCH NEXT FROM col INTO #ColumnName
END
CLOSE col
SET #HTMLROWS=#HTMLROWS + ''</tr>''
END
SET #OUTPUT=''''
IF #maxrows>0
SET #OUTPUT= ''<table ' + #TBL_STYLE + '>'' + #FIELDS + #HTMLROWS + ''</table>''
DEALLOCATE col
'
DECLARE #ParamDefinition nvarchar(max)
SET #ParamDefinition=N'#OUTPUT NVARCHAR(MAX) OUTPUT'
--Execute Dynamic SQL. HTML table is stored in #OUTPUT which is passed back up (as it's
--a parameter to this SP)
EXEC sp_executesql #exec_str,
#ParamDefinition,
#OUTPUT=#OUTPUT OUTPUT
RETURN 1;
---- VIEW VERSION SQL--
GO
create view versao_sql as
SELECT Convert(nvarchar(30),SERVERPROPERTY('MachineName')) AS [NOME DA MAQUINA] ,
Convert(nvarchar(30),SERVERPROPERTY('InstanceName')) AS [INSTANCIA] ,
Convert(nvarchar(30),SERVERPROPERTY('ProductVersion')) AS [PRODUCT VERSION],
Convert(nvarchar(30),SERVERPROPERTY('ProductLevel')) AS [PRODUCT LEVEL] ,
Convert(nvarchar(30),SERVERPROPERTY('Edition')) AS [EDIÇÃO] ,
( CASE SERVERPROPERTY('EngineEdition')
WHEN 1 THEN 'Personal or Desktop'
WHEN 2 THEN 'Standard'
WHEN 3 THEN 'Enterprise'
else ''
END ) AS [ENGINE TYPE] ,
Convert(nvarchar(30),SERVERPROPERTY('LicenseType')) AS [TIPO DE LICENÇA] ,
convert(nvarchar(30), SERVERPROPERTY('NumLicenses')) AS [LICENÇAS] ,
( CASE SERVERPROPERTY('IsIntegratedSecurityOnly')
WHEN 0 THEN 'Mista'
WHEN 1 THEN 'Integrada'
else ''
END ) AS [SOMENTE SEGURANÇA INTEGRADA] ,
convert(nvarchar(30),SERVERPROPERTY('Collation')) AS [COLLATION] ,
( CASE SERVERPROPERTY('IsClustered')
WHEN 0 THEN 'Nao'
WHEN 1 THEN 'Sim'
END ) AS [CLUSTER];
------INFO INSTANCE--
GO
create view info_instancia as
select 'VERSAO DO CHECK LIST' as DESCRICAO,'2.2.6' as VALOR
union all
select 'NOME DO SERVIDOR' as DESCRICAO, CAST(##SERVERNAME as nvarchar) as VALOR
union all
select 'IP DO SERVIDOR' as DESCRICAO, CAST(CONNECTIONPROPERTY('local_net_address') as nvarchar) as VALOR
union all
select 'NOME DA INSTANCIA' as DESCRICAO, CAST(SERVERPROPERTY('InstanceName') as nvarchar) as VALOR
union all
select 'NLS_CHARACTERSET' as DESCRICAO, CAST(SERVERPROPERTY('Collation') as nvarchar) as VALOR
union all
select 'VERSAO SQL SERVER' as DESCRICAO, CAST(##VERSION as nvarchar) as VALOR
union all
select 'DATA DE HOJE' as DESCRICAO, CAST(GETDATE() as nvarchar) as VALOR;
-- RUNNING PROCEDURE FOR EACH VIEW
GO
--SQL VERSION
declare #html nvarchar(max)
exec SqlTableToHtml 'versao_sql', #html output, 'style="table:"border=1 width=65%"', '', 'style="scope=col"'
select #html;
GO
--INSTANCE SQL
declare #html nvarchar(max)
exec SqlTableToHtml 'info_instancia', #html output, 'style="table:"border=1 width=65%"', '', 'style="scope=col"'
select #html;
----DROPINGS----
GO
drop view versao_sql;
GO
drop view info_instancia;
GO
DROP PROCEDURE SqlTableToHtml;

SQL Server stored procedure with parameters for table name, ID field, ID field value that is uniqueidentifier

I have about 12 tables in the database that are simple baseline data. As an example, I have Role and Status. These tables have an ID that is a uniqueidentifier. I'm trying to create a stored procedure that will allow me to pass the table name, name of the ID column, and the value I want.
I've tried this:
ALTER PROCEDURE [dbo].[GET_TABLE_DATA_BY_ID]
#table nvarchar(50),
#tableid uniqueidentifier,
#value uniqueidentifier
AS
BEGIN
SET NOCOUNT ON;
DECKALE #cmd AS nvarchar(max)
SET #cmd = N'select * ' +
'from ' + #table +
'where ' + cast(#tableid as nvarchar) + '= #value'
EXEC sp_executesql #cmd
END
The procedure adds fine. But when I execute the procedure I get this error:
Msg 8114, Level 16, State 5, Procedure GET_TABLE_DATA_BY_ID, Line 0
Error converting data type nvarchar to uniqueidentifier.
Is this even possible? Otherwise I would have to write many different procedures, not to mention the many different C# functions.
When I right click on the procedure and enter the values to test it creates this:
DECLARE #return_value int
EXEC #return_value = [dbo].[GET_TABLE_DATA_BY_ID]
#table = N'UserProfile',
#tableid = UserId,
#value = 'FB743B78-5B90-4A52-8177-6D516884700B'
SELECT 'Return Value' = #return_value
GO
I get the error :
Error converting data type nvarchar to uniqueidentifier.
I redid the procedure per suggestion to this:
DECLARE #cmd NVARCHAR(MAX) =
N'SELECT *
FROM #table
WHERE tableid = #value',
#param_list NVARCHAR(MAX) =
N'#table NVARCHAR(50),
#tableid UNIQUEIDENTIFIER';
EXEC [dbo].[sp_executesql]
#cmd
,#param_list
,#table
,#tableid;
When I do this in a new query window, I get the right data:
select * from UserProfile where UserId = 'FB743B78-5B90-4A52-8177-6D516884700B'
But it doesn't work when I execute the proc with those values -
Msg 105, Level 15, State 1, Line 4
Unclosed quotation mark after the character string '#value'.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near '#value'.
Use explicit parameters:
SqlFiddleDemo
DECLARE
#tablename NVARCHAR(100) = 'tab1',
#tableid NVARCHAR(100) = 'a',
#value UNIQUEIDENTIFIER = '2FD22D07-E128-4133-ABA9-9B75215CB465'
DECLARE
#cmd NVARCHAR(MAX) =
N'SELECT *
FROM ' + QUOTENAME(#tablename) +
'WHERE ' + QUOTENAME(#tableid) + ' = #value'
EXEC [dbo].[sp_executesql]
#cmd
, N'#value UNIQUEIDENTIFIER'
, #value

T-SQL function with dynamic SELECT (not possible) - solved with procedure instead

I've managed to use EXEC sp_executesql in a one off statement to do a dynamic lookup, but am unable to adjust the code to create a function since EXEC is not allowed in functions. It works in procedures and I've managed to get output via PRINT for a single lookup by using a temporary table, but really that was just me struggling to find a workaround. Ideally I'd like to be able to create a scalar-value function.
The reason that I need a dynamic lookup is because the column name is stored in another table.
Here's a quick breakdown of the tables:
Questions:
Columns: Q_Group, Q_Nbr, Question_Desc, Data_Field
Sample data: 'R3', 5, 'Do you have any allergies?', 'TXT_04'
Responses:
Columns: Order_Nbr, Q_Group, TXT_01, TXT_02, TXT_03, TXT_04, etc.
Data: 999, 'R3', 'blah', 'blah', 'blah', 'NO'
Orders will be assigned a particular set of questions 'Q_Group' and often a particular question will be the same across various different sets of questions. The problem is that when the set/groups of questions were set up, the questions may not have been added in the same order, and thus the responses go into different columns.
So here's where I'm at...
I can get 'TXT_04' from the Data_Field column in Questions and use EXEC sp_executesql to do a lookup for a single order, but am struggling to find a way to accomplish this as a function of some sort.
DECLARE #col_name VARCHAR(6)
DECLARE #sql VARCHAR(100)
SET #col_name = SELECT Data_Field FROM QUESTIONS WHERE Q_Group = 'R3'
AND Question_Desc = 'Do you have any allergies?'
SET #sql = 'SELECT ' + #col_name + ' FROM RESPONSES WHERE Order_Nbr = 999'
EXEC sp_executesql #sql
I'm just at a loss as to how this could be incorporated into a function so that I could get responses for several orders in a result set. Any workarounds possible? Maybe I'm totally off base using EXEC sp_executesql?
Thanks.
Edit...
Okay, I've changed the title to reflect that I'm going to consider this solved with a procedure instead of a function, as it ended up getting the output that I wanted. Which was a table with all of the corresponding responses.
Here's the code that I settled on. I decided to use LIKE to match the Question_Desc instead of equals, and then included the Question_Desc in the results, so that it could be used a bit more broadly. Thankfully it's pretty quick to run currently. Although that could always change as the database grows!
CREATE PROCEDURE get_all_responses (#question_txt VARCHAR(255))
AS
DECLARE #response_col VARCHAR(35)
DECLARE #t TABLE (order_nbr int, question_txt VARCHAR(255), response_col VARCHAR(35), response VARCHAR(255))
DECLARE #i TABLE (id INT PRIMARY KEY IDENTITY(1,1), response_col VARCHAR(35))
DECLARE #u TABLE (order_nbr int, response VARCHAR(255))
DECLARE #sql VARCHAR(200)
INSERT #t
SELECT Order_Nbr, Question_Desc, Data_Field, NULL
FROM Responses
JOIN (
SELECT Q_Group, Question_Desc, Data_Field
FROM Questions
WHERE Question_Desc LIKE #question_txt
) #Q ON Q_Group = #Q.Q_Group
WHERE Q_Group <> '0'
ORDER BY Data_Field, Order_Nbr
-- Stop if no results found and return empty result set
IF (SELECT COUNT(*) FROM #t) = 0
BEGIN
SELECT order_nbr, question_txt, response FROM #t
RETURN
END
INSERT #i SELECT response_col FROM #t GROUP BY response_col
DECLARE #row_nbr int
DECLARE #last_row int
SET #row_nbr = 1
SET #last_row = (SELECT COUNT(*) FROM #i)
-- Iterate through each Data_Field found
WHILE #row_nbr <= #last_row
BEGIN
SET #response_col = (SELECT response_col FROM #i WHERE id = #row_nbr)
SET #sql = 'SELECT Order_Nbr, ' + #response_col + ' FROM Responses WHERE NullIf(' + #response_col + ','''') IS NOT NULL'
INSERT INTO #u
EXEC (#sql)
UPDATE #t
SET response = y.response
FROM #t AS x
INNER JOIN #u AS y ON x.order_nbr = y.order_nbr
SET #row_nbr = #row_nbr + 1
END
-- Remove results with no responses
DELETE FROM #t WHERE response IS NULL
SELECT order_nbr, question_txt, response FROM #t
RETURN
You will not be able to execute dynamic SQL from within a function but you could do this with a stored procedure and capture the output.
DECLARE #col_name VARCHAR(6), #param NVARCHAR(50), #myReturnValue VARCHAR(50)
SET #param = N'#result VARCHAR(50) OUTPUT'
DECLARE #sql VARCHAR(100)
SET #col_name = SELECT Data_Field FROM QUESTIONS WHERE Q_Group = 'R3'
AND Question_Desc = 'Do you have any allergies?'
SET #sql = 'SELECT #result = ' + #col_name + ' FROM RESPONSES WHERE Order_Nbr = 999'
EXEC sp_executesql #sql, #param, #result = #myReturnValue output
--manipulate value here
print #myReturnValue
You could also create a temp table and do an insert into from exec sp_executesql.

Cast in SQL Server query

I am having a problem with executing one SQL query, Below is my stored procedure
Query
ALTER PROCEDURE ProcName
(
#iID VARCHAR(50),
#AccountID INT
)
AS
SET NOCOUNT ON
DECLARE #Sql VARCHAR(MAX)
SET #Sql = 'DELETE FROM ReferringPhysician WHERE iID IN(' + #iID + ') AND AccountID = '+ #AccountID + ''
EXEC (#Sql)
I am trying to execute this query but it gives me error because i am using exec(), Here in my where condition i am dealing with the string, and in another condition i am dealing with the int, so in second condition i am getting casting error! how can i get through this?
Any help is greatly Appreciated!
Thanks
Your query is susceptible to SQL injection.
One way to avoid the data type problem you are having is to pass proper data types where you can and not use EXEC() (more details here):
DECLARE #sql NVARCHAR(MAX) = N'DELETE dbo.referringPhysician
WHERE iID IN (' + #iID + ') AND AccountID = #AccountID;';
EXEC sp_executesql #sql, N'#AccountID INT', #AccountID;
You can completely protect this from SQL injection by using table-valued parameters and passing in a DataTable or other collection with proper types instead of a comma-delimited string. e.g.:
CREATE TYPE dbo.iIDs TABLE(iID INT PRIMARY KEY);
Now your stored procedure can avoid dynamic SQL altogether:
ALTER PROCEDURE dbo.ProcName -- always use schema prefix!
#iIDs dbo.iIDs READONLY,
#AccountID INT
AS
BEGIN
SET NOCOUNT ON;
DELETE r
FROM dbo.ReferringPhysician AS r
INNER JOIN #iIDs AS i
ON r.iID = i.iID
WHERE r.AccountID = #AccountID;
END
GO
Try this:
ALTER PROCEDURE ProcName
(
#iID VARCHAR(50),
#AccountID INT
)
AS
SET NOCOUNT ON
DECLARE #Sql VARCHAR(MAX)
SET #Sql = 'DELETE FROM ReferringPhysician WHERE iID IN(' + CAST(#iID AS VARCHAR) + ') AND AccountID = '+ CAST(#AccountID AS VARCHAR) + ''
EXEC (#Sql)

How to CREATE TYPE type_name AS existing_table_name

Is there a way to create table type in SQL Server 2008 based on scheme of existing table?
CREATE TABLE A (id INT, name VARCHAR(30))
CREATE TYPE type_a AS TABLE.A
Something like that.
No, this kind of composable DML is not yet possible. Microsoft has rejected this suggestion in the past, but with enough votes (e.g. more than 1!) it may get reconsidered in the future:
http://connect.microsoft.com/SQLServer/feedback/details/294130/table-valued-parameters-add-support-for-create-type-type-from-table-table-name-options-syntax-construct
You can use following stored procedure to create a type with same schema existing table may have.
Create PROCEDURE [dbo].[Sp_DefineTypeOutOfTableSchema]
#TableNames NVARCHAR(500)
AS
BEGIN
DECLARE #TableName NVARCHAR(100)
DECLARE #strSQL NVARCHAR(max)
DECLARE #strSQLCol NVARCHAR(1000)
DECLARE #ColName NVARCHAR(100)
DECLARE #ColDataTaype NVARCHAR(50)
DECLARE #ColDefault NVARCHAR(50)
DECLARE #ColIsNulable NVARCHAR(50)
DECLARE #ColCharMaxlen NVARCHAR(50)
DECLARE #ColNumPrec NVARCHAR(50)
DECLARE #ColNumScal NVARCHAR(50)
IF LEN(#TableNames) > 0 SET #TableNames = #TableNames + ','
WHILE LEN(#TableNames) > 0
BEGIN
SELECT #TableName = LTRIM(SUBSTRING(#TableNames, 1, CHARINDEX(',', #TableNames) - 1))
DECLARE schemaCur CURSOR FOR
SELECT COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =#TableName
OPEN schemaCur
SELECT #strSQL=''
FETCH NEXT FROM schemaCur
INTO #ColName,#ColDataTaype,#ColIsNulable,#ColDefault,#ColCharMaxlen,#ColNumPrec,#ColNumScal
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #strSQLCol=''
SELECT #strSQLCol= '['+#ColName+'] '+'[' + #ColDataTaype +'] '
IF #ColDataTaype='nvarchar' or #ColDataTaype='char' or #ColDataTaype='varchar' or #ColDataTaype='vchar'
BEGIN
SELECT #strSQLCol=#strSQLCol+ '(' + #ColCharMaxlen +') '
END
ELSE IF #ColDataTaype='numeric' or #ColDataTaype='decimal'
BEGIN
SELECT #strSQLCol=#strSQLCol +'(' + #ColNumPrec +',' +#ColNumScal + ') '
END
IF #ColIsNulable='YES'
BEGIN
SELECT #strSQLCol=#strSQLCol+ 'NULL '
END
ELSE
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' NOT NULL '
END
IF #ColDefault IS NOT NULL
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' DEFAULT(' +#ColDefault + '),'
END
ELSE
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' ,'
END
SELECT #strSQL=#strSQL+#strSQLCol
--print #strSQL
FETCH NEXT FROM schemaCur
INTO #ColName,#ColDataTaype,#ColIsNulable,#ColDefault,#ColCharMaxlen,#ColNumPrec,#ColNumScal
END
CLOSE schemaCur
DEALLOCATE schemaCur
--print #strSQL
SELECT #strSQL=left( #strSQL, len(#strSQL)-1)
--print #strSQL
IF EXISTS (SELECT * FROM sys.types WHERE IS_TABLE_TYPE = 1 AND name = 't_' +#TableName)
BEGIN
EXEC('DROP TYPE t_' +#TableName )
END
SELECT #strSQL = 'CREATE TYPE t_' + #TableName + ' AS TABLE (' + #strSQL + ')'
--print #strSQL
EXEC (#strSQL)
SELECT #TableNames = SUBSTRING(#TableNames, CHARINDEX(',', #TableNames) + 1, LEN(#TableNames))
END
END
you can use it like this
Exec Sp_DefineTypeOutOfTableSchema 'Table1name,Table2name'
You could experiment with creating a function that pulled the table definition out of sysobjects, systypes, syscolumns, syscomments, etc., and built a CREATE statement out of it. You'd just have to make sure to grab all of the important pieces (columns, constraints, comments, etc.) from the various sys tables.
Then call it like... EXEC myCREATEtable #template_table_name or some such...