When I execute the stored procedure, I get this error:
Msg 8114, Level 16, State 5, Procedure SPXML, Line 158
Error converting data type varchar to numeric.
I'm using a stored procedure and cursor for the first time.
This is my stored procedure:
CREATE PROCEDURE [dbo].[SPXML]
(#CounterStockMaster text,
#CounterStockDetails text,
#CounterStock text)
AS
DECLARE #M0 VARCHAR(100) --EditStatus
DECLARE #M1 VARCHAR(100) --Counter_Code
DECLARE #M2 VARCHAR(100) --Counter_Name
DECLARE #M3 VARCHAR(100) --To Branch_Code
DECLARE #D1 VARCHAR(100) --Project Type
DECLARE #D2 VARCHAR(100) --drpC.Text
DECLARE #D3 VARCHAR(100) --grdGO.Rows[i].Cells["1"].Value
DECLARE #D4 VARCHAR(100) --grdGO.Rows[i].Cells["2"].Value
DECLARE #D5 VARCHAR(100)
DECLARE #C1 VARCHAR(100) --Cnt Code
DECLARE #C2 VARCHAR(100) --Item
DECLARE #C3 VARCHAR(100) --Qty
BEGIN
DECLARE #CNTNo VARCHAR(100)
DECLARE #idoc INT
DECLARE #INDate Datetime
DECLARE #Branch_Code NUMERIC(18,0)
DECLARE #ItemCode NUMERIC(18,0)
DECLARE #ItemQty NUMERIC(18,3)
DECLARE #PurRate NUMERIC(18,2)
DECLARE #SaleRate NUMERIC(18,2)
DECLARE #MRP NUMERIC(18,2)
DECLARE #PurDate DATETIME
DECLARE #Batch_No VARCHAR(50)
DECLARE #ExpiryDate DATETIME
DECLARE #MultiMRP BIT
BEGIN TRANSACTION
SET DATEFORMAT dmy
SET #MultiMRP = (Select ISNULL(Multiple_Mrp,0) from [Company])
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStockMaster
DECLARE GINMasterCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CSMASTER/ID',1)
WITH (M0 VARCHAR(100), M1 VARCHAR(100), M2 VARCHAR(100),M3 VARCHAR(100))
OPEN GINMasterCursor
FETCH NEXT FROM GINMasterCursor INTO #M0,#M1,#M2,#M3
IF #M0='T' ---Edit Mode TRUE
BEGIN --- Reversing the Item Stock for the Editing Sales START
SET #CNTNo = #M1
DECLARE GInDetailCursor CURSOR FOR
SELECT Counter_Stock_Code,Item_Code,Item_Qty,Branch_Code From [CntDetails]
WHERE Counter_Stock_Code = #CNTNo AND Branch_Code=#M3
OPEN GInDetailCursor
FETCH NEXT FROM GInDetailCursor INTO #CNTNo,#ItemCode,#ItemQty,#Branch_Code
WHILE ##FETCH_STATUS=0
BEGIN
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL - #ItemQty , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #ItemCode and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL - #ItemQty , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #ItemCode and Item_MRP = #MRP and Type_Code = 0 and Branch_Code = #M3
FETCH NEXT FROM GInDetailCursor INTO #CNTNo,#ItemCode,#ItemQty,#Branch_Code
END
CLOSE GInDetailCursor
DEALLOCATE GInDetailCursor
END --- Reversing the Item Stock for the Editing GO END
ELSE
BEGIN
SET #CNTNo = (SELECT ISNULL(MAX(Counter_Stock_Code)+1,1) FROM [Counter Stock Master] where Branch_Code = #M3)
END
INSERT INTO [CntMaster]
(Counter_Stock_Code,Counter_Stock_Date,Branch_Code)
VALUES
(#CNTNo, #INDate, #M3)
CLOSE GINMasterCursor
DEALLOCATE GINMasterCursor
EXEC sp_xml_removedocument #idoc
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStockDetails
-- Execute a SELECT statement using OPENXML rowset provider.
DECLARE GInDetailsCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CSDETAILS/ID',1)
WITH ( D1 VARCHAR(100), D2 VARCHAR(100), D3 VARCHAR(100), D4 VARCHAR(100))
OPEN GInDetailsCursor
FETCH NEXT FROM GInDetailsCursor INTO #D1,#D2,#D3,#D4
WHILE ##FETCH_STATUS = 0
BEGIN
IF #D1='A' or #D1='D' --For ProjectType ==> Departmental Stores
BEGIN
SET #D2 = #CNTNo
INSERT INTO [CntDetails]
(Counter_Stock_Code,Item_Code,Item_Qty,Branch_Code)
VALUES
(#D2, #D3, #D4, #M3)
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
END
FETCH NEXT FROM GInDetailsCursor INTO #D1,#D2,#D3,#D4
END
CLOSE GInDetailsCursor
DEALLOCATE GInDetailsCursor
***[EXEC sp_xml_removedocument #idoc ----------------------- "I get this error from this line"][1]***
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStock
-- Execute a SELECT statement using OPENXML rowset provider.
DECLARE CSCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CounterStock/ID',1)
WITH ( D1 VARCHAR(100), D2 VARCHAR(100), D3 VARCHAR(100), D4 VARCHAR(100))
OPEN CSCursor
FETCH NEXT FROM CSCursor INTO #D1,#D2,#D3,#D4
WHILE ##FETCH_STATUS = 0
BEGIN
IF #D1='A' or #D1='D' --For ProjectType ==> Departmental Stores
BEGIN
INSERT INTO [CntStock]
(Conter_Code,Item_Code,Item_Qty)
VALUES
(#D2, #D3, #D4)
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
END
FETCH NEXT FROM CSCursor INTO #D1,#D2,#D3,#D4
END
CLOSE CSCursor
DEALLOCATE CSCursor
EXEC sp_xml_removedocument #idoc
SELECT #CNTNo
COMMIT TRANSACTION
END
GO
I tried many times but i didn't solve this problem.
Does anyone have any suggestions?
Error here:
INSERT INTO [CntStock]
(Conter_Code,Item_Code,Item_Qty)
VALUES
(#D2, #D3, #D4) ---DECLARE #D4 VARCHAR(100) ---What is the type of 'Item_Qty' column in CntStock table,Is it numeric,You are assigning varchar to numberic field.
Try changing the type of #D4
Related
I am inserting records using stored procedure and sp_executesql. Once I insert record using sp_executesql, i need the last inserted identity field value on that session.
ALTER proc [dbo].[spHoldTransaction]
#RegisterNo int,
#StoreID int,
#Department varchar(50),
#TransactionDateFrom date,
#TransactionDateTo date,
#Comment Varchar(50)
AS
BEGIN
DECLARE #RegisterID int;
DECLARE #DatabaseName varchar(15);
DECLARE #Batch int;
SELECT #RegisterID=ID FROM Register WHERE Register.Number = #RegisterNo;
SELECT #Batch = BatchNumber From Batch WHERE Status = 0 and RegisterID = #RegisterID
SET #DatabaseName = 'xxx'
SELECT #Department=''''+REPLACE(#Department,',',''',''')+''''
DECLARE #Qry nvarchar(MAX);
DECLARE #ParamDefinition nvarchar(MAX);
SET #ParamDefinition = N'#comment nvarchar(50),#StoreID int,#Batch int'
SET #Qry = '
INSERT INTO '+#DatabaseName+'.dbo.TransactionHold
(
[StoreID]
,[HoldComment]
,[BatchNumber]
,[ShippingNotes]
)
SELECT
#StoreID AS [StoreID]
,#Comment AS [HoldComment]
,#Batch AS [BatchNumber]
,'''' AS [ShippingNotes];
'
EXECUTE sp_executesql #Qry, #ParamDefinition, #Comment, #StoreID, #Batch
SELECT SCOPE_IDENTITY()
END
When I execute this above stored procedure, it's return empty. But TransactionHold has identity column Id
Try retrieving the identity inside the same scope of the execute sql procedure and return the value as an OUT parameter. Do these changes:
SET #ParamDefinition = N'#comment nvarchar(50),#StoreID int,#Batch int, #identity int out'
SET #Qry = '
INSERT INTO '+#DatabaseName+'.dbo.TransactionHold
(
[StoreID]
,[HoldComment]
,[BatchNumber]
,[ShippingNotes]
)
SELECT
#StoreID AS [StoreID]
,#Comment AS [HoldComment]
,#Batch AS [BatchNumber]
,'''' AS [ShippingNotes];
SET #identity = ##IDENTITY
'
DECLARE #identity INT
EXECUTE sp_executesql #Qry, #ParamDefinition, #Comment, #StoreID, #Batch, #identity OUT
SELECT #identity
I tried to define following SQL Server nested cursor statement: I loop calendars and migrate them from cut_calendar to sd_calendar. Each calendar also have calendar days. They are also moved by each calendar move.
DECLARE #id NUMERIC(20)
DECLARE #sdCalendarId NUMERIC(20)
DECLARE #calendarTypId NUMERIC(5)
DECLARE #name NVARCHAR(35)
DECLARE #description NVARCHAR(255)
DECLARE #ptyId NUMERIC(20)
DECLARE #lockCode NVARCHAR(20)
DECLARE #dataOwnerId NUMERIC(20)
DECLARE #cntId NUMERIC(20)
DECLARE #nonBusinessDaysMonday CHAR(1)
DECLARE #nonBusinessDaysTuesday CHAR(1)
DECLARE #nonBusinessDaysWednesday CHAR(1)
DECLARE #nonBusinessDaysThursday CHAR(1)
DECLARE #nonBusinessDaysFriday CHAR(1)
DECLARE #nonBusinessDaysSaturday CHAR(1)
DECLARE #nonBusinessDaysSunday CHAR(1)
DECLARE #ccyId NUMERIC(20)
DECLARE #code NVARCHAR(30)
DECLARE #version NUMERIC(10)
DECLARE #seal VARCHAR(255)
DECLARE #lstUpdTs DATETIME
DECLARE #day_id NUMERIC(20)
DECLARE #day_calDate DATETIME
DECLARE #day_lockCode NVARCHAR(20)
DECLARE #day_calComment NVARCHAR(255)
DECLARE #day_dataOwnerId NUMERIC(20)
DECLARE #day_calendarId NUMERIC(20)
DECLARE #day_calRecurring CHAR(1)
DECLARE #day_version NUMERIC(10)
DECLARE #day_seal VARCHAR(255)
DECLARE #day_lstUpdTs DATETIME
DECLARE #day_sdCalendarDaysId NUMERIC(20)
DECLARE #sdCodeId NUMERIC(20)
DECLARE cursorCutoffCalendar CURSOR FOR
SELECT ID, NAME, CALENDAR_TYP_ID,DESCRIPTION,PTY_ID,LOCK_CODE,DATA_OWNER_ID,CNT_ID,NON_BUSINESS_DAYS_MONDAY,NON_BUSINESS_DAYS_TUESDAY,NON_BUSINESS_DAYS_WEDNESDAY,NON_BUSINESS_DAYS_THURSDAY,NON_BUSINESS_DAYS_FRIDAY,NON_BUSINESS_DAYS_SATURDAY,NON_BUSINESS_DAYS_SUNDAY,CCY_ID,CODE,VERSION,SEAL,LST_UPD_TS
FROM CUT_CALENDAR
WHERE ID != 1
OPEN cursorCutoffCalendar
FETCH NEXT FROM cursorCutoffCalendar INTO #id, #name, #calendarTypId, #description, #ptyId, #lockCode, #dataOwnerId, #cntId, #nonBusinessDaysMonday, #nonBusinessDaysTuesday, #nonBusinessDaysWednesday, #nonBusinessDaysThursday, #nonBusinessDaysFriday, #nonBusinessDaysSaturday, #nonBusinessDaysSunday, #ccyId, #code, #version, #seal, #lstUpdTs
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #sdCalendarId = COALESCE(MAX(ID),1) FROM SD_CALENDAR
SET #sdCalendarId = #sdCalendarId + 1
UPDATE CUT_CALENDAR_DAY
SET CALENDAR_ID = #sdCalendarId
WHERE CALENDAR_ID = #id
SELECT #sdCodeId = ID FROM SD_CALENDAR WHERE CODE = #code
IF #sdCodeId > 0
SET #code = CONCAT(#code, '_co')
ELSE
INSERT INTO SD_CALENDAR (ID, NAME, CALENDAR_ROLE_ID,DESCRIPTION,USE_IN_CUTOFF,PTY_ID,LOCK_CODE,DATA_OWNER_ID,CNT_ID,NON_BUSINESS_DAYS_MONDAY,NON_BUSINESS_DAYS_TUESDAY,NON_BUSINESS_DAYS_WEDNESDAY,NON_BUSINESS_DAYS_THURSDAY,NON_BUSINESS_DAYS_FRIDAY,NON_BUSINESS_DAYS_SATURDAY,NON_BUSINESS_DAYS_SUNDAY,CCY_ID,CODE,VERSION,SEAL,LST_UPD_TS)
VALUES(#sdCalendarId, #name, #calendarTypId,#description,1,#ptyId,#lockCode,#dataOwnerId,#cntId,#nonBusinessDaysMonday,#nonBusinessDaysTuesday,#nonBusinessDaysWednesday,#nonBusinessDaysThursday,#nonBusinessDaysFriday,#nonBusinessDaysSaturday,#nonBusinessDaysSunday,#ccyId,#code,#version,#seal,#lstUpdTs)
DECLARE cursorCutoffCalendarDays CURSOR FOR
SELECT ID, CAL_DATE, LOCK_CODE,CAL_COMMENT,DATA_OWNER_ID,CALENDAR_ID,CAL_RECURRING,VERSION,SEAL,LST_UPD_TS
FROM CUT_CALENDAR_DAY
WHERE ID != 1
OPEN cursorCutoffCalendarDays
FETCH NEXT FROM cursorCutoffCalendarDays INTO #day_id, #day_calDate, #day_lockCode, #day_calComment, #day_dataOwnerId, #day_calendarId, #day_calRecurring, #day_version, #day_seal, #day_lstUpdTs
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #day_sdCalendarDaysId = COALESCE(MAX(ID),1) FROM SD_CALENDAR_DAY
SET #day_sdCalendarDaysId = #day_sdCalendarDaysId + 1
INSERT INTO SD_CALENDAR_DAY (ID, CAL_DATE, LOCK_CODE,CAL_COMMENT,DATA_OWNER_ID,CALENDAR_ID,CAL_RECURRING,VERSION,SEAL,LST_UPD_TS)
VALUES(#day_sdCalendarDaysId, #day_calDate, #day_lockCode, #day_calComment, #day_dataOwnerId, #day_calendarId, #day_calRecurring, #day_version, #day_seal, #day_lstUpdTs)
FETCH NEXT FROM cursorCutoffCalendarDays INTO #day_sdCalendarDaysId, #day_calDate, #day_lockCode, #day_calComment, #day_dataOwnerId, #day_calendarId, #day_calRecurring, #day_version, #day_seal, #day_lstUpdTs
END
CLOSE cursorCutoffCalendarDays
DEALLOCATE cursorCutoffCalendarDays
GO
DELETE FROM CUT_CALENDAR
WHERE ID = #id
FETCH NEXT FROM cursorCutoffCalendar INTO #sdCalendarId, #name, #calendarTypId, #description, #ptyId, #lockCode, #dataOwnerId, #cntId, #nonBusinessDaysMonday, #nonBusinessDaysTuesday, #nonBusinessDaysWednesday, #nonBusinessDaysThursday, #nonBusinessDaysFriday, #nonBusinessDaysSaturday, #nonBusinessDaysSunday, #ccyId, #code, #version, #seal, #lstUpdTs
END
CLOSE cursorCutoffCalendar
DEALLOCATE cursorCutoffCalendar
GO
Now when I run this, I get following error:
SQLServerException: Incorrect syntax near 'cursorCutoffCalendarDays'.
cursorCutoffCalendarDays is the inner cursor of my statement.
Try removing GO from:
CLOSE cursorCutoffCalendarDays
DEALLOCATE cursorCutoffCalendarDays
GO
And I agree with the comment you got from GarethD, I used to write cursors like this but then I asked how to do it without the cursor and got a nice explanation
Blockquote
Remove Go from this line then try
CLOSE cursorCutoffCalendarDays
DEALLOCATE cursorCutoffCalendarDays
I have stored Procedure for Search.
ALTER Proc [dbo].[USP_GETFAQ]
#SortBy Varchar(128)='CreatedDate DESC',
#Page int=1,
#RecsPerPage int =10,
#Status Char(5)='',
#Question varchar(500)='',
#Answer varchar(1000)=''
As
DECLARE #SQL VARCHAR(MAX)
DECLARE #DSQL VARCHAR(MAX)
DECLARE #whereCondition VARCHAR(1024)
DECLARE #FirstRec int, #LastRec int
SET #FirstRec = (#Page - 1) * #RecsPerPage
SET #LastRec = (#Page * #RecsPerPage + 1)
Declare #SectionCount int;
Set NoCount On
Begin
SET #SQL='Select
ROW_NUMBER() over( order by '+#SortBy +') rownum,
* FROM faq where Status <>''D'''
if #Status !='' and #Status is not null AND #Status!='ALL'
begin
SET #SQL+=' AND Status = '''+#Status+''''
end
if #Question!=''
begin
SET #SQL +=' AND Question like '''+'%'+REPLACE(#Question, '''', '')+'%'+''''
end
if #Answer!=''
begin
SET #SQL +=' AND Answer like '''+'%'+REPLACE(#Answer, '''', '')+'%'+''''
end
SET #DSQL='SELECT * from (' + #SQL +') AS tbl'
print #DSQL
DECLARE #TEMPResult TABLE(RowNum INT,
ID uniqueIdentifier,
Question varchar(500),
Answer varchar(1000),
CreatedDate DateTime,
LastModifiedDate dateTime,
CreatedByIp varchar(20),
LastModifiedByIp varchar(20),
CreatedBy varchar(50),
ModifiedBy varchar(50),
[Order] int,
Status char(5)
)
INSERT INTO #TEMPResult EXEC(#DSQL)
SELECT (Select Count(*) from #TEMPResult) as Count,ID,SUBSTRING(question, 1, 200)question ,SUBSTRING(Answer, 1,250)Answer,
CreatedDate,LastModifiedDate,CreatedByIp ,LastModifiedByIp,CreatedBy,ModifiedBy, [Order], Status FROM #TEMPResult WHERE RowNum > #FirstRec AND RowNum < #LastRec
RETURN
End
When a question or answer contains "'" i getting error. that synatx is wrong near "'".
What i have tried so far is:
i have replaced the "'" with "''''" before passing the string to stored proc. it run successfully but not returning any record, please help me how can i do it.
Your method will lead to sql injection
MSDN SQL injection
Try to use EXEC sp_executesql #SQLString, #ParamDef, #paramList ...
MSDN sp_executesql
Your code:
ALTER Proc [dbo].[USP_GETFAQ]
#SortBy Varchar(128)='CreatedDate DESC',
#Page int=1,
#RecsPerPage int =10,
#Status Char(5)='',
#Question varchar(500)='',
#Answer varchar(1000)=''
As
DECLARE #SQL NVARCHAR(MAX)
DECLARE #FirstRec int, #LastRec int
SET #FirstRec = (#Page - 1) * #RecsPerPage
SET #LastRec = (#Page * #RecsPerPage + 1)
Declare #SectionCount int;
Set NoCount On
Begin
SET #SQL='SELECT * from (
Select ROW_NUMBER() over( order by '+#SortBy +') rownum,
* FROM faq where Status <>''D'''
if #Status !='' and #Status is not null AND #Status!='ALL'
begin
SET #SQL+=' AND Status = #Status '
end
if #Question!=''
begin
SET #Question = '%'+#Question+'%'
SET #SQL +=' AND Question like #Question'
end
if #Answer!=''
begin
SET #Answer = '%'+#Answer+'%'
SET #SQL +=' AND Answer like #Answer'
end
SET #SQL += ') AS tbl'
print #SQL
DECLARE #ParamDefinition nvarchar(4000)
SET #ParamDefinition =
'#Status Char(5),
#Question varchar(500),
#Answer varchar(1000)';
DECLARE #TEMPResult TABLE(RowNum INT,
ID uniqueIdentifier,
Question varchar(500),
Answer varchar(1000),
CreatedDate DateTime,
LastModifiedDate dateTime,
CreatedByIp varchar(20),
LastModifiedByIp varchar(20),
CreatedBy varchar(50),
ModifiedBy varchar(50),
[Order] int,
Status char(5)
)
INSERT INTO #TEMPResult
EXECUTE sp_executesql #SQL, #ParamDefinition
,#Status = #Status
,#Question = #Question
,#Answer = #Answer
SELECT (Select Count(*) from #TEMPResult) as Count,ID,SUBSTRING(question, 1, 200)question ,SUBSTRING(Answer, 1,250)Answer,
CreatedDate,LastModifiedDate,CreatedByIp ,LastModifiedByIp,CreatedBy,ModifiedBy, [Order], Status FROM #TEMPResult WHERE RowNum > #FirstRec AND RowNum < #LastRec
RETURN
End
Use 3 single quotes in a row. Like '''. Do not use any double quotes.
I have this stored procedure in SQL Server:
alter PROCEDURE [dbo].[spSendLogLinesAsXML]
(
#device_id varchar(128),
#application_name VARCHAR(64),
#application_user_name VARCHAR(6),
#log_lines_xml XML
)
AS
BEGIN
DECLARE
#ixml INT,
#log_line_dt DATETIME,
#log_line_message varchar(max)
EXEC sp_xml_preparedocument #ixml OUTPUT,
#log_lines_xml
SELECT #log_line_dt = dt,
#log_line_message = data
FROM OPENXML(#ixml, '/lines/line', 3) WITH (
dt DATETIME,
data varchar(max)
)
--I want to do the following for each line element
EXEC spSendLogLine
#device_id = #device_id,
#application_name = #application_name,
#application_user_name = #application_user_name,
#log_line_dt = #log_line_dt,
#log_line_message = #log_line_message
EXEC sp_xml_removedocument #ixml
return -100
END
I call the stored procedure like this:
EXEC #return_value = [dbo].[spSendLogLinesAsXML]
#device_id = N'devid123',
#application_name = N'CJA App 1',
#application_user_name = N'anatoli',
#log_lines_xml = '<lines><line><dt>2013-03-01T13:00:00</dt><data>Something happened and it was logged</data></line><line><dt>2013-03-01T13:01:00</dt><data>Oh my god the building is burning and people are dying</data></line></lines>'
How can I modify my stored procedure to call spSendLogLine for each line element?
Edit: According to SQL - Call Stored Procedure for each record cursors are bad. So I want to know a better way. I don't mind how much my stored procedure is changed to achieve this, as long as it ends up working properly and is nice.
alter PROCEDURE [dbo].[spSendLogLinesAsXML]
(
#device_id varchar(128),
#application_name VARCHAR(64),
#application_user_name VARCHAR(6),
#log_lines_xml XML
)
AS
BEGIN
declare #log_line_dt datetime,
#log_line_message varchar(1024)
declare #curse cursor
set #curse = cursor fast_forward for
select n.d.value('dt[1]', 'datetime') as log_line_dt, n.d.value('data[1]', 'varchar(1024)') as log_line_message
from #log_lines_xml.nodes('/lines/line') n(d)
open #curse
fetch next from #curse into #log_line_dt, #log_line_message
while (##fetch_status = 0)
begin
EXEC spSendLogLine
#device_id = #device_id,
#application_name = #application_name,
#application_user_name = #application_user_name,
#log_line_dt = #log_line_dt,
#log_line_message = #log_line_message
fetch next from #curse into #log_line_dt, #log_line_message
end
close #curse;
return -100
END
GO
This is what I ended up with, following muhmud's answer. Still wish someone would tell me how to do it sans cursors.
ALTER PROCEDURE [dbo].[spSendLogLinesAsXML]
(
#device_id VARCHAR(128),
#application_name VARCHAR(64),
#application_user_name VARCHAR(6),
#log_lines_xml XML
)
AS
BEGIN
DECLARE #ixml INT,
#log_line_dt DATETIME,
#log_line_message VARCHAR(max),
#cursor CURSOR
SET #cursor = CURSOR FAST_FORWARD
FOR
SELECT n.d.value('dt[1]', 'datetime') AS log_line_dt,
n.d.value('data[1]', 'varchar(max)') AS log_line_message
FROM #log_lines_xml.nodes('/lines/line') n(d)
OPEN #cursor
FETCH NEXT
FROM #cursor
INTO #log_line_dt,
#log_line_message
WHILE (##fetch_status = 0)
BEGIN
EXEC spSendLogLine #device_id = #device_id,
#application_name = #application_name,
#application_user_name = #application_user_name,
#log_line_dt = #log_line_dt,
#log_line_message = #log_line_message
FETCH NEXT
FROM #cursor
INTO #log_line_dt,
#log_line_message
END
RETURN - 100
END
If you're using SQL Server 2008 or newer, you could do something like this:
define a user-defined table type that holds all the columns that are relevant to your procedure:
CREATE TYPE dbo.SendLogLineType
AS TABLE (LineDate DATETIME2(3), LineData VARCHAR(200), DeviceID VARCHAR(128),
ApplicationName VARCHAR(64), AppUserName VARCHAR(6) )
then, extract your lines into that table, and add the other "fixed" parameters (this happens inside your [spSendLogLinesAsXML] procedure):
DECLARE #InputTable dbo.SendLogLineType
INSERT INTO #InputTable(LineDate, LineData, DeviceID, ApplicationName, AppUserName)
SELECT
XLine.value('(dt)[1]', 'DATETIME2'),
XLine.value('(data)[1]', 'varchar(200)'),
#device_id,
#application_name,
#application_user_name
FROM
#log_lines_xml.nodes('/lines/line') AS XTbl(XLine)
and lastly, change your spSendLogLine procedure to accept a table valued parameter of that defined table type and change its logic so that it will iterate over all rows that get passed into it:
CREATE PROCEDURE spSendLogLine
(#SendLogLineData dbo.SendLogLineType READONLY)
AS
BEGIN
-- iterate over all rows in #SendLogLineData and send out those e-mails!
END
Read more about Table-Valued Parameters on the relevant MSDN SQL Server Books Online documentation page
I have a sql stored procedure which calls another sql stored procedure. I works fine when excuted in sql server. But when I called from function in class it returns the DataTable returned by subprocedure. I want to return data returned by main procedure.
My Main Procedure:
ALTER PROCEDURE [dbo].[StoredProcedure2]
#QuaterList varchar(50) = NULL
AS
BEGIN
DECLARE #sql nvarchar(4000)
SELECT #sql='SELECT Id, Suggester, Requester, Date_Created from CRM.dbo.CRM_Doctor_Request WHERE 1=1 '
If (#QuaterList) IS NOT NULL
BEGIN
DECLARE #MonthsList varchar(1000)
EXEC dbo.SPGetMonthsListforMultipleQuaters #QuaterList, #MonthsList OUTPUT
SELECT #MonthsList
SELECT #sql=#sql + ' AND MONTH(Date_Created) in ('
+ SUBSTRING(#MonthsList, 1, LEN(#MonthsList)-1) +')'
END
EXEC sp_executesql #sql, N' #QuaterList varchar(50) ',
#QuaterList
END
Sub Procedure SPGetMonthsListforMultipleQuaters:
ALTER PROCEDURE dbo.SPGetMonthsListforMultipleQuaters
#InputList varchar(10),
#MonthsList varchar(1000) OUTPUT
AS
BEGIN
SELECT #MonthsList= ''
/* Create temp table */
CREATE TABLE #TempListTable
(
TableField int
)
/* add data into temp table */
DECLARE #TableField varchar(10), #Pos int
SET #InputList = LTRIM(RTRIM(#InputList))+ ','
SET #Pos = CHARINDEX(',', #InputList, 1)
IF REPLACE(#InputList, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #TableField = LTRIM(RTRIM(LEFT(#InputList, #Pos - 1)))
IF #TableField <> ''
BEGIN
INSERT INTO #TempListTable (TableField) VALUES (CAST(#TableField AS int)) --Use Appropriate conversion
END
SET #InputList = RIGHT(#InputList, LEN(#InputList) - #Pos)
SET #Pos = CHARINDEX(',', #InputList, 1)
END
END
/* fetch data from temptable using cursor */
DECLARE #ArrayItem nvarchar(100)
DECLARE #Array_Cursor CURSOR
SET #Array_Cursor = CURSOR FAST_FORWARD FOR select TableField
from #TempListTable
OPEN #Array_Cursor
FETCH NEXT FROM #Array_Cursor INTO #ArrayItem
WHILE ##FETCH_STATUS = 0
BEGIN
/* creating list of months */
IF (#ArrayItem = 1)
SELECT #MonthsList=#MonthsList + '4,5,6,'
IF (#ArrayItem = 2)
SELECT #MonthsList=#MonthsList + '7,8,9,'
IF (#ArrayItem = 3)
SELECT #MonthsList=#MonthsList + '10,11,12,'
IF (#ArrayItem = 4)
SELECT #MonthsList=#MonthsList + '1,2,3,'
FETCH NEXT FROM #Array_Cursor INTO #ArrayItem
END
/*print #MonthsList*/
Close #Array_Cursor
deallocate #Array_Cursor
END
Problem solved. It was because I wrote SELECT #MonthsList so it was returning that too which is not required, and was also creating problems. So I removed it and problem solved.
New Procedure code is :
ALTER PROCEDURE [dbo].[StoredProcedure2]
#QuaterList varchar(50) = NULL
AS
BEGIN
DECLARE #sql nvarchar(4000)
SELECT #sql='SELECT Id, Suggester, Requester, Date_Created from CRM.dbo.CRM_Doctor_Request WHERE 1=1 '
If (#QuaterList) IS NOT NULL
BEGIN
DECLARE #MonthsList varchar(1000)
EXEC dbo.SPGetMonthsListforMultipleQuaters #QuaterList, #MonthsList OUTPUT
SELECT #sql=#sql + ' AND MONTH(Date_Created) in ('
+ SUBSTRING(#MonthsList, 1, LEN(#MonthsList)-1) +')'
END
EXEC sp_executesql #sql, N' #QuaterList varchar(50) ',
#QuaterList
END