Stored procedure name proc1
Parameters are @param1, @param2, @param3
Values are 1,2,3
declare @SqlString nvarchar(2000)
declare @ParamDef nvarchar(2000)
set @SqlString = N'exec proc1 @param1, @param2, @param3'
set @ParamDef = N'@param1 bit, @param2 bit, @param3 bit'
EXECUTE sp_executesql @SqlString ,@ParamDef, @param1 = 0, @param2 = 1, @param3 = 1
This blog is created to add all the information and experiences that I have learnt while working on MS sql server as a DBA. The blog is also updated frequently with the real world problem that I encounter hands on at work and the resolutions to resolve them. I hope this blog will be of some use to you and you will revisit. Thank you for stopping by and you are welcome to leave comments.
Friday, December 27, 2013
Thursday, June 27, 2013
Schedule a SQL profiler to run at a specific time
I needed to reserach some external backups on the database that ran in the middle of the night. To find out the source and the status. I decided to set up a trace in sql profiler that consisted teh processID, Loginame, NTusername etc .
Steps on SQL Server 2008 R2
---
If you run the follwing query you will see our trace
select * from ::fn_trace_getinfo(0)
Immediately stop the trace
Now we want to export the create trace script and add this script as one of the step in the schedule job
Click on File----Select Export--Select Script Trace Definition
Select the entire script and add it as a step in the schedule job.
In the script - Search for key word in the script 'InsertFileNameHere' and replace with where to store the trace file.
exec @rc = sp_trace_create @TraceID output, 0, N'E:\profilertrace\trace1.trc', @maxfilesize, @Datetime
Save the Job.
That's all !!! Schedule the job to run at the specific time that you would like it to run.
Steps on SQL Server 2008 R2
---
- Connect to SSMS
- Go to Tools
- Go to SQL Profiler
- Chose the appropriate trace template according to requirements ( or create your own)
- Check enable trace stop time and specify the date and time that you want it to stop
- Click on the Run
If you run the follwing query you will see our trace
select * from ::fn_trace_getinfo(0)
Immediately stop the trace
Now we want to export the create trace script and add this script as one of the step in the schedule job
Click on File----Select Export--Select Script Trace Definition
Select the entire script and add it as a step in the schedule job.
In the script - Search for key word in the script 'InsertFileNameHere' and replace with where to store the trace file.
exec @rc = sp_trace_create @TraceID output, 0, N'E:\profilertrace\trace1.trc', @maxfilesize, @Datetime
That's all !!! Schedule the job to run at the specific time that you would like it to run.
Tuesday, June 18, 2013
Giving execute permission to all stored procedures through a databaserole
I had a situation where I had to give a user( AD group) execution permission to all the sps.
- Created a role called db_executor data user role
USE pubs
GO
GO
exec sp_addrole 'db_executor'
GO
--added memebers to the role
USE pubs
GO
GO
exec sp_addrolemember 'db_executor', 'GRP_ProdSupport'
GO
--gave permission to execute the stored procedures to the role.
USE pubs
GO
DECLARE @SQL nvarchar(4000),
@Owner sysname,
@StoredProcedure sysname,
@Return int
-- Cursor of all the stored procedures in the current database
DECLARE cursStoredProcedures CURSOR FAST_FORWARD
FOR
SELECT USER_NAME(uid) Owner, [name] StoredProcedure
FROM sysobjects
WHERE xtype = 'P'
OPEN cursStoredProcedures
-- "Prime the pump" and get the first row
FETCH NEXT FROM cursStoredProcedures
INTO @Owner, @StoredProcedure
-- Set the return code to 0
SET @Return = 0
-- Encapsulate the permissions assignment within a transaction
BEGIN TRAN
-- Cycle through the rows of the cursor
-- And grant permissions
WHILE ((@@FETCH_STATUS = 0) AND (@Return = 0))
BEGIN
-- Create the SQL Statement. Since we're giving
-- access to all stored procedures, we have to
-- use a two-part naming convention to get the owner.
SET @SQL = 'GRANT EXECUTE ON [' + @Owner
+ '].[' + @StoredProcedure
+ '] TO db_executor'
-- Execute the SQL statement
EXEC @Return = sp_executesql @SQL
-- Get the next row
FETCH NEXT FROM cursStoredProcedures
INTO @Owner, @StoredProcedure
END
-- Clean-up after the cursor
CLOSE cursStoredProcedures
DEALLOCATE cursStoredProcedures
-- Check to see if the WHILE loop exited with an error.
IF (@Return = 0)
BEGIN
-- Exited fine, commit the permissions
COMMIT TRAN
END
ELSE
BEGIN
-- Exited with an error, rollback any changes
ROLLBACK TRAN
-- Report the error
SET @SQL = 'Error granting permission to ['
+ @Owner + '].[' + @StoredProcedure + ']'
RAISERROR(@SQL, 16, 1)
END
GO
GO
DECLARE @SQL nvarchar(4000),
@Owner sysname,
@StoredProcedure sysname,
@Return int
-- Cursor of all the stored procedures in the current database
DECLARE cursStoredProcedures CURSOR FAST_FORWARD
FOR
SELECT USER_NAME(uid) Owner, [name] StoredProcedure
FROM sysobjects
WHERE xtype = 'P'
OPEN cursStoredProcedures
-- "Prime the pump" and get the first row
FETCH NEXT FROM cursStoredProcedures
INTO @Owner, @StoredProcedure
-- Set the return code to 0
SET @Return = 0
-- Encapsulate the permissions assignment within a transaction
BEGIN TRAN
-- Cycle through the rows of the cursor
-- And grant permissions
WHILE ((@@FETCH_STATUS = 0) AND (@Return = 0))
BEGIN
-- Create the SQL Statement. Since we're giving
-- access to all stored procedures, we have to
-- use a two-part naming convention to get the owner.
SET @SQL = 'GRANT EXECUTE ON [' + @Owner
+ '].[' + @StoredProcedure
+ '] TO db_executor'
-- Execute the SQL statement
EXEC @Return = sp_executesql @SQL
-- Get the next row
FETCH NEXT FROM cursStoredProcedures
INTO @Owner, @StoredProcedure
END
-- Clean-up after the cursor
CLOSE cursStoredProcedures
DEALLOCATE cursStoredProcedures
-- Check to see if the WHILE loop exited with an error.
IF (@Return = 0)
BEGIN
-- Exited fine, commit the permissions
COMMIT TRAN
END
ELSE
BEGIN
-- Exited with an error, rollback any changes
ROLLBACK TRAN
-- Report the error
SET @SQL = 'Error granting permission to ['
+ @Owner + '].[' + @StoredProcedure + ']'
RAISERROR(@SQL, 16, 1)
END
GO
Labels:
Administration,
database role,
dynamic sql,
execute,
permissions,
script,
sql2008,
stored procedures
Permission to run a specific SQL job to a user
I added a user to the msdb database and gave him the SQLAgentUserRole but that gave him access to all the jobs, which is not what I wanted. This is the work around I followed....
USE msdb
GO
CREATE PROC dbo.Start_Job_MyJobThatAGroupControls
-- Executes as the database owner, for msdb that is 'sa'
WITH EXECUTE AS OWNER
AS
-- Hardcoding the job name limits this procedure's control
EXEC dbo.sp_start_job @job_name = 'MyProductionJobName'
GO
-- Grant Execute rights to your selected users
GRANT EXECUTE ON Start_Job_MyJobThatAGroupControls TO <usernames>
GO
This way the user will not have direct access to the job MyProductionJobName but through this wrapper sp it can run the job.
USE msdb
GO
CREATE PROC dbo.Start_Job_MyJobThatAGroupControls
-- Executes as the database owner, for msdb that is 'sa'
WITH EXECUTE AS OWNER
AS
-- Hardcoding the job name limits this procedure's control
EXEC dbo.sp_start_job @job_name = 'MyProductionJobName'
GO
-- Grant Execute rights to your selected users
GRANT EXECUTE ON Start_Job_MyJobThatAGroupControls TO <usernames>
GO
This way the user will not have direct access to the job MyProductionJobName but through this wrapper sp it can run the job.
Labels:
Administration,
execute,
msdb,
permissions,
sql 2008,
SQL Agent Jobs
Tuesday, March 12, 2013
SQL server side traces handy commands
select * from ::fn_trace_getinfo(0) //list all the traces--where property = 5
--stops the tracet of raceid 2 EXEC sp_trace_setstatus 2 ,0
---restart the trace of traceid 2
EXEC sp_trace_setstatus 2 ,1
--deletes the trace of traceid 2 from the server EXEC sp_trace_setstatus 2 ,2
--stops the tracet of raceid 2 EXEC sp_trace_setstatus 2 ,0
---restart the trace of traceid 2
EXEC sp_trace_setstatus 2 ,1
--deletes the trace of traceid 2 from the server EXEC sp_trace_setstatus 2 ,2
Labels:
Administration,
serverside trace,
sql,
sql profiler,
trace
Thursday, January 17, 2013
Resending the failed mails in DBmail
We had several failed mail items that were supposed to be sent out overnight by some SQL Jobs.
The following query was run to find the failed items
use msdb
GO
declare @StartDate datetime,
@EndDate datetime
select * from dbo.sysmail_faileditems where last_mod_date >=@StartDate and last_mod_date < @EndDate
--all the returned rows had sent_status as failed.
Here is a very cool script that will resend the failed items that I found in sqlservercentral.com. It worked like a charm!!!
declare @mailitem_id int, @sendmailxml
varchar(max), @rc
int,@StartDate datetime, @EndDate
datetime-- get the dates to use in the queryset @StartDate = convert(datetime, convert(char(8), GetDate(), 112))set @EndDate = @StartDate + 1declare cFailedMail cursor forSELECT
mailitem_id
FROM [msdb].[dbo].[sysmail_faileditems]
WHERE send_request_date >= @StartDate
AND send_request_date < @EndDateopen cFailedMail
fetch next from cFailedMail into @mailitem_id
while @@fetch_status = 0
begin
-- Create the primary SSB xml maessage
SET @sendmailxml = '<requests:SendMail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/databasemail/requests RequestTypes.xsd" xmlns:requests="http://schemas.microsoft.com/databasemail/requests"><MailItemId>'+ CONVERT(NVARCHAR(20), @mailitem_id) + N'</MailItemId></requests:SendMail>'-- Send the send request on queue.EXEC @rc = sp_SendMailQueues @sendmailxml
IF @rc <> 0BEGIN
RAISERROR(14627, 16, 1, @rc, 'send mail')END
fetch next from cFailedMail into @mailitem_idend
close cFailedMail
deallocate cFailedMail
The following query was run to find the failed items
use msdb
GO
declare @StartDate datetime,
@EndDate datetime
select * from dbo.sysmail_faileditems where last_mod_date >=@StartDate and last_mod_date < @EndDate
--all the returned rows had sent_status as failed.
Here is a very cool script that will resend the failed items that I found in sqlservercentral.com. It worked like a charm!!!
declare @mailitem_id int, @sendmailxml
varchar(max), @rc
int,@StartDate datetime, @EndDate
datetime-- get the dates to use in the queryset @StartDate = convert(datetime, convert(char(8), GetDate(), 112))set @EndDate = @StartDate + 1declare cFailedMail cursor forSELECT
mailitem_id
FROM [msdb].[dbo].[sysmail_faileditems]
WHERE send_request_date >= @StartDate
AND send_request_date < @EndDateopen cFailedMail
fetch next from cFailedMail into @mailitem_id
while @@fetch_status = 0
begin
-- Create the primary SSB xml maessage
SET @sendmailxml = '<requests:SendMail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/databasemail/requests RequestTypes.xsd" xmlns:requests="http://schemas.microsoft.com/databasemail/requests"><MailItemId>'+ CONVERT(NVARCHAR(20), @mailitem_id) + N'</MailItemId></requests:SendMail>'-- Send the send request on queue.EXEC @rc = sp_SendMailQueues @sendmailxml
IF @rc <> 0BEGIN
RAISERROR(14627, 16, 1, @rc, 'send mail')END
fetch next from cFailedMail into @mailitem_idend
close cFailedMail
deallocate cFailedMail
Wednesday, January 9, 2013
Using table valued parameters to insert multiple rows in VB.NET
Dim Table1 As DataTable
'create a table named tmptblTable1 = New DataTable("tmptbl")
Dim Row1, Row2, Row3, Row4, Row5 As DataRow
'establishing connection. you need to provide password for SQL serverDim sConn As New SqlConnection()
Dim sSqlcommand As New SqlCommand()
Try'declare a column named Ptno Dim intPtno As DataColumn = New DataColumn("Ptno")
'setting the datatype for the columnintPtno.DataType = System.Type.GetType("System.Int32")
'adding the column to tableTable1.Columns.Add(intPtno)
Dim intUserId As DataColumn = New DataColumn("UserId")intUserId.DataType = System.Type.GetType(
"System.Int32")Table1.Columns.Add(intUserId)
Dim intDocType As DataColumn = New DataColumn("DocTypeId")intDocType.DataType = System.Type.GetType(
"System.Int32")Table1.Columns.Add(intDocType)
Dim strSessionId As DataColumn = New DataColumn("UserSessionId")strSessionId.DataType = System.Type.GetType(
"System.String")Table1.Columns.Add(strSessionId)
If Request.QueryString("Doc1") <> "0" Then'declaring a new rowRow1 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row1.Item("Ptno") = ptnoRow1.Item(
"UserId") = userIdRow1.Item(
"DocTypeId") = Doc1Row1.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row1)
End IfIf Request.QueryString("Doc2") <> "0" Then'declaring a new rowRow2 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row2.Item("Ptno") = ptnoRow2.Item(
"UserId") = userIdRow2.Item(
"DocTypeId") = Doc2Row2.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row2)
End IfIf Request.QueryString("Doc3") <> "0" Then'declaring a new rowRow3 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row3.Item("Ptno") = ptnoRow3.Item(
"UserId") = userIdRow3.Item(
"DocTypeId") = Doc3Row3.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row3)
End IfIf Request.QueryString("Doc4") <> "0" Then'declaring a new rowRow4 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row4.Item("Ptno") = ptnoRow4.Item(
"UserId") = userIdRow4.Item(
"DocTypeId") = Doc4Row4.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row4)
End IfIf Request.QueryString("Doc5") <> "0" Then'declaring a new rowRow5 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row5.Item("Ptno") = ptnoRow5.Item(
"UserId") = userIdRow5.Item(
"DocTypeId") = Doc5Row5.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row5)
End If
sConn.ConnectionString = ConfigurationManager.ConnectionStrings("StatusUpdatesConnectionString").ToString()sConn.Open()
sSqlcommand = sConn.CreateCommand()
sSqlcommand.CommandType = CommandType.StoredProcedure
sSqlcommand.CommandText =
"PROC_PV_ACCOUNT_DOCTYPE_INSERT"sSqlcommand.CommandTimeout = 3600
sSqlcommand.Connection = sConn
sSqlcommand.Parameters.Add("@DocTypeTbl", SqlDbType.Structured).Value = Table1sSqlcommand.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception(ex.Message)
FinallysSqlcommand.Dispose()
If sConn.State = ConnectionState.Open ThensConn.Close()
sConn = NothingEnd IfEnd Try
'create a table named tmptblTable1 = New DataTable("tmptbl")
Dim Row1, Row2, Row3, Row4, Row5 As DataRow
'establishing connection. you need to provide password for SQL serverDim sConn As New SqlConnection()
Dim sSqlcommand As New SqlCommand()
Try'declare a column named Ptno Dim intPtno As DataColumn = New DataColumn("Ptno")
'setting the datatype for the columnintPtno.DataType = System.Type.GetType("System.Int32")
'adding the column to tableTable1.Columns.Add(intPtno)
Dim intUserId As DataColumn = New DataColumn("UserId")intUserId.DataType = System.Type.GetType(
"System.Int32")Table1.Columns.Add(intUserId)
Dim intDocType As DataColumn = New DataColumn("DocTypeId")intDocType.DataType = System.Type.GetType(
"System.Int32")Table1.Columns.Add(intDocType)
Dim strSessionId As DataColumn = New DataColumn("UserSessionId")strSessionId.DataType = System.Type.GetType(
"System.String")Table1.Columns.Add(strSessionId)
If Request.QueryString("Doc1") <> "0" Then'declaring a new rowRow1 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row1.Item("Ptno") = ptnoRow1.Item(
"UserId") = userIdRow1.Item(
"DocTypeId") = Doc1Row1.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row1)
End IfIf Request.QueryString("Doc2") <> "0" Then'declaring a new rowRow2 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row2.Item("Ptno") = ptnoRow2.Item(
"UserId") = userIdRow2.Item(
"DocTypeId") = Doc2Row2.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row2)
End IfIf Request.QueryString("Doc3") <> "0" Then'declaring a new rowRow3 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row3.Item("Ptno") = ptnoRow3.Item(
"UserId") = userIdRow3.Item(
"DocTypeId") = Doc3Row3.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row3)
End IfIf Request.QueryString("Doc4") <> "0" Then'declaring a new rowRow4 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row4.Item("Ptno") = ptnoRow4.Item(
"UserId") = userIdRow4.Item(
"DocTypeId") = Doc4Row4.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row4)
End IfIf Request.QueryString("Doc5") <> "0" Then'declaring a new rowRow5 = Table1.NewRow()
'filling the row with values. Item property is used to set the field value.Row5.Item("Ptno") = ptnoRow5.Item(
"UserId") = userIdRow5.Item(
"DocTypeId") = Doc5Row5.Item(
"UserSessionId") = appSessionIdTable1.Rows.Add(Row5)
End If
sConn.ConnectionString = ConfigurationManager.ConnectionStrings("StatusUpdatesConnectionString").ToString()sConn.Open()
sSqlcommand = sConn.CreateCommand()
sSqlcommand.CommandType = CommandType.StoredProcedure
sSqlcommand.CommandText =
"PROC_PV_ACCOUNT_DOCTYPE_INSERT"sSqlcommand.CommandTimeout = 3600
sSqlcommand.Connection = sConn
sSqlcommand.Parameters.Add("@DocTypeTbl", SqlDbType.Structured).Value = Table1sSqlcommand.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception(ex.Message)
FinallysSqlcommand.Dispose()
If sConn.State = ConnectionState.Open ThensConn.Close()
sConn = NothingEnd IfEnd Try
Using table valued parameters to insert multiple rows into a database table
Before Table-Valued Parameters were introduced in SQL Server 2008, programmers had to pass multi-row data as serialized, delimited, strings, long parameter lists, or XML. Now using TVP ( table Value parameters we can send all the rows in one transactio to the Sql server without having to make round trips, this will boost the performance.
For example let's say we have to insert the following data to the table
Ptno, DocTypeId, UserId,UserSessionId
34343,1,614,354354545
45554,2,614,456566666
14563,3,614,456366336
The above data needs to be inserted into the table
CREATE TABLE [dbo].[PV_Account_DocType](
[PVId] [int] IDENTITY(1,1) NOT NULL,
[Ptno] [int] NOT NULL,
[DocTypeId] [int] NOT NULL,
[UserId] [int] NOT NULL,
[DateEntered] [datetime] NOT NULL,
[UserSessionId] [varchar](100) NULL
) ON [PRIMARY]
Where PVID is the identity value and dateentered has the default value of getdate()
The first step is we create the Table Type "DocType" in the User Defined table types section
CREATE TYPE [dbo].[DocType] AS TABLE(
[Ptno] [int] NOT NULL,
[UserId] [int] NULL,
[DocTypeId] [int] NULL,
[UserSessionId] [varchar](100) NULL
)
GO
Now that the TPV is defined we need to make it usable. For example if we want to insert data or use any other T-SQL, we have to create a variable of the new table type and populate it. For those familiar with Object Oriented Programming, this is a bit like instantiating a class or object. Once this new variable is created it will inherit the table structure of the new type. This is how it is done:
First of all we declare a variable of table type:
DECLARE @Mytabletype DocType
/* The variable name @Mtabletype can be called anything you want but the table type has to reference an existing table definition type. Now we insert the data: */INSERT INTO @Mytabletype (ptno, UserId,DocTypeId,UserSessionId)VALUES (34343,1,614,'354354545'),
(45554,2,614,'456566666'),
(14563,3,614,'456366336');
/* Once the table is populated, we can manipulate the data like any other table, provided the variable is in scope: */SELECT * FROM @Mytabletype
We get the following result
So what does the code above do? Well, first of all, we define the stored procedure by adding our table type DocType then we add a READONLY qualifier. This qualifier is very important and MUST be included when a stored procedure is created. This is mainly because Transact-SQL passes table-valued parameters to routines by reference. Basically, a pointer is passed to the stored procedure and not as we would have expected, the user defined table variable. It therefore isn’t possible to do DML operations that update a table-valued parameter, such as UPDATE, DELETE, or INSERT within a routine. Table-valued parameters are read-only in Transact-SQL code. If you need to modify the data that is passed to a stored procedure or parameterized statement in a table-valued parameter, you will need to insert the data into a temporary table or into a table variable first. It isn’t actually much of a problem to do this, and takes little time.
We now use the stored procedure to insert the data
exec PROC_PV_ACCOUNT_DOCTYPE_INSERT @DocTypeTbl = @Mytabletype
The sp is coded as follows
CREATE PROC PROC_PV_ACCOUNT_DOCTYPE_INSERT(@DocTypeTbl DocType READONLY )AS
INSERT INTO PV_Account_DocType(Ptno, DocTypeId, UserId,UserSessionId)
SELECT Ptno, DocTypeId, UserId,UserSessionId
FROM @DocTypeTblGO
For example let's say we have to insert the following data to the table
Ptno, DocTypeId, UserId,UserSessionId
34343,1,614,354354545
45554,2,614,456566666
14563,3,614,456366336
The above data needs to be inserted into the table
CREATE TABLE [dbo].[PV_Account_DocType](
[PVId] [int] IDENTITY(1,1) NOT NULL,
[Ptno] [int] NOT NULL,
[DocTypeId] [int] NOT NULL,
[UserId] [int] NOT NULL,
[DateEntered] [datetime] NOT NULL,
[UserSessionId] [varchar](100) NULL
) ON [PRIMARY]
Where PVID is the identity value and dateentered has the default value of getdate()
The first step is we create the Table Type "DocType" in the User Defined table types section
CREATE TYPE [dbo].[DocType] AS TABLE(
[Ptno] [int] NOT NULL,
[UserId] [int] NULL,
[DocTypeId] [int] NULL,
[UserSessionId] [varchar](100) NULL
)
GO
Now that the TPV is defined we need to make it usable. For example if we want to insert data or use any other T-SQL, we have to create a variable of the new table type and populate it. For those familiar with Object Oriented Programming, this is a bit like instantiating a class or object. Once this new variable is created it will inherit the table structure of the new type. This is how it is done:
First of all we declare a variable of table type:
DECLARE @Mytabletype DocType
/* The variable name @Mtabletype can be called anything you want but the table type has to reference an existing table definition type. Now we insert the data: */INSERT INTO @Mytabletype (ptno, UserId,DocTypeId,UserSessionId)VALUES (34343,1,614,'354354545'),
(45554,2,614,'456566666'),
(14563,3,614,'456366336');
/* Once the table is populated, we can manipulate the data like any other table, provided the variable is in scope: */SELECT * FROM @Mytabletype
We get the following result
So what does the code above do? Well, first of all, we define the stored procedure by adding our table type DocType then we add a READONLY qualifier. This qualifier is very important and MUST be included when a stored procedure is created. This is mainly because Transact-SQL passes table-valued parameters to routines by reference. Basically, a pointer is passed to the stored procedure and not as we would have expected, the user defined table variable. It therefore isn’t possible to do DML operations that update a table-valued parameter, such as UPDATE, DELETE, or INSERT within a routine. Table-valued parameters are read-only in Transact-SQL code. If you need to modify the data that is passed to a stored procedure or parameterized statement in a table-valued parameter, you will need to insert the data into a temporary table or into a table variable first. It isn’t actually much of a problem to do this, and takes little time.
We now use the stored procedure to insert the data
exec PROC_PV_ACCOUNT_DOCTYPE_INSERT @DocTypeTbl = @Mytabletype
The sp is coded as follows
CREATE PROC PROC_PV_ACCOUNT_DOCTYPE_INSERT(@DocTypeTbl DocType READONLY )AS
INSERT INTO PV_Account_DocType(Ptno, DocTypeId, UserId,UserSessionId)
SELECT Ptno, DocTypeId, UserId,UserSessionId
FROM @DocTypeTblGO
Subscribe to:
Posts (Atom)