I have a table named Table1 which contains an ID and TimeStamp.
Table structure
ID TimeStamp
1 0x0000000000047509
But when I compare the combination of these fields, it always shows false. What is the reason for this?
My Query is :
DECLARE #ID int
DECLARE #TimeStamp timestamp
SET #ID = 1
SET #TimeStamp = 0x0000000000047509
If EXISTS(SELECT 1 FROM Table1 WHERE ID = #ID AND TimeStamP = #TimeStamp)
BEGIN
SELECT 1 AS RetVal
END
ELSE
BEGIN
SELECT -1 AS RetVal
END
My stored procedure is as follows
CREATE PROCEDURE [dbo].[Check] (
#XMLDoc ntext
)AS
BEGIN
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE #ID bigint
DECLARE #TimeStamp timestamp
DECLARE #hDoc int
EXEC sp_xml_PrepareDocument #hDoc OUT, #XMLDoc
SELECT #ID = ID
,#TimeStamp = [TimeStamp]
FROM OPENXML (#hdoc,'/XML')
WITH ( ID bigint 'ID'
,[TimeStamp] timestamp 'TStamp')
IF ##ERROR<>0
BEGIN
EXEC sp_xml_RemoveDocument #hDoc
SELECT -620 AS RetVal
RETURN
END
IF NOT EXISTS(SELECT 1 FROM Table1 WHERE ID= #ID AND Timestamp = #TimeStamp )
BEGIN
SELECT -1 AS RetVal
END
ELSE
BEGIN
SELECT 1 AS RetVal
END
END
That's odd, the query works fine for me in SQL Server 2005, compatibility mode 80.
The only thing that jumps out to me is that Timestamp is a reserved word, so to be on the safe side you might want to add brackets around Timestamp to escape it as follows:
If EXISTS(SELECT 1 FROM Table1 WHERE [ID] = #ID AND [TimeStamP] = #TimeStamp) ...
#TimeStamp is not being resolved correctly from the XML. Try CASTing it to binary(8).
The stored proc does not match the query you posted earlier
Related
I'm trying to execute a stored procedure which inputs 3 parameters selected from a query. The first 2 stored procedure parameters are supposed to be int or bigint, but sql doesn't accept it and tell me it cannot convert type nvarchar to bigint.
So I changed the parameter types to nvarchar but now I get this error when executing a query within the stored procedure. I tried to convert nvarchar to bigint but it doesn't work even though the parameter values are numeric.
Here's how I'm executing the stored procedure:
[dbo].[InsertMultiChoiceList] [PatientRiskAssessmentQuestionsID], NetworkRiskAssessmentQuestionsID, Answer
The parameters being passed on look like these:
230124| 118 |COPD (Chronic Obstructive Pulmonary Disease), Congestive Heart Failure (CHF), Sleep Apnea
Here the definition of my stored procedure:
ALTER PROCEDURE [dbo].[InsertMultiChoiceList]
#PatientRiskAssessmentQuestionsID nvarchar(100),
#NetworkRiskAssessmentQuestionsID nvarchar(100),
#answer varchar(max)
AS
BEGIN
DECLARE #XML AS XML
DECLARE #Delimiter AS CHAR(1) =','
SET #XML = CAST(('<X>'+REPLACE(#answer , #Delimiter ,'</X><X>')+'</X>') AS XML)
DECLARE #temp TABLE (Answer Varchar(max))
INSERT INTO #temp
SELECT N.value('.', 'Varchar(max)') AS Answer
FROM #XML.nodes('X') AS T(N)
INSERT INTO [dbo].[PatientRiskAssessmentQuestionsList](NetworkRiskAssessmentListID, PatientRiskAssessmentQuestionsID)
SELECT
[dbo].[fnc_GetNetworkRiskAssessmentList](LTRIM(RTRIM(q.Answer)), #NetworkRiskAssessmentQuestionsID, 'List') AS NetworkRiskAssessmentListID,
#PatientRiskAssessmentQuestionsID
FROM
(SELECT Answer FROM #temp) q
WHERE
NOT EXISTS (SELECT 1
FROM PatientRiskAssessmentQuestionsList x
WHERE x.NetworkRiskAssessmentListID = NetworkRiskAssessmentListID
AND x.PatientRiskAssessmentQuestionsID = #PatientRiskAssessmentQuestionsID);
END
Here's the structure of the PatientRiskAssessmentQuestionsList table
Here's the script for fnc_GetNetworkRiskAssessmentList
ALTER function [dbo].[fnc_GetNetworkRiskAssessmentList]
(#text varchar(max),
#networkriskquestionid bigint,
#type varchar(20)
)
RETURNS BIGINT
AS
BEGIN
declare #id bigint
declare #questionid bigint
declare #count int
set #id = null
set #questionid = null
set #count = 0
if(#type = 'List')
begin
select #count = Count(*)
from NetworkRiskAssessmentList mc
where mc.Answer = #text
and mc.NetworkRiskAssessmentQuestionsID = #networkriskquestionid
if #count > 0
begin
select top(1) #questionid = mc.NetworkRiskAssessmentListID
from NetworkRiskAssessmentList mc
where mc.Answer = #text
and mc.NetworkRiskAssessmentQuestionsID = #networkriskquestionid
set #id = #questionid
end
end
return #questionid
end
The issue is you are trying to push a string value into the column NetworkRiskAssessmentListID which is actually BIGINT thus SQL doesn't allow the conversion.
Just a sample code to show you the issue
CREATE TABLE #Test
(
Patient BIGINT,
Network BIGINT
)
GO
DECLARE #Patient NVARCHAR(100)
DECLARE #Network NVARCHAR(100)
SET #Patient = '1234'
SET #Network = 'List'
INSERT INTO #Test VALUES (#Patient,#Network)
Hope this helps, try changing the datatype of the table and give it a try.
maybe your data has Enter character or Tab character so use code like below :
DECLARE #XML AS XML
DECLARE #Delimiter AS CHAR(1) =','
SET #XML = CAST(('<X>'+REPLACE(#answer , #Delimiter ,'</X><X>')+'</X>') AS XML)
DECLARE #temp TABLE (Answer Varchar(max))
INSERT INTO #temp
SELECT N.value('.', 'Varchar(max)') AS Answer FROM #XML.nodes('X') AS T(N)
insert into [dbo].[PatientRiskAssessmentQuestionsList](NetworkRiskAssessmentListID, PatientRiskAssessmentQuestionsID)
select
[dbo].[fnc_GetNetworkRiskAssessmentList](LTRIM(RTRIM(q.Answer)), #NetworkRiskAssessmentQuestionsID, 'List') as NetworkRiskAssessmentListID,
#PatientRiskAssessmentQuestionsID
from
(select cast(replace(replace(Answer, char(13), ''), char(10), '') as bigint) as Answer from #temp) q
where not exists
(
select 1 from PatientRiskAssessmentQuestionsList x
where x.NetworkRiskAssessmentListID = NetworkRiskAssessmentListID and x.PatientRiskAssessmentQuestionsID = #PatientRiskAssessmentQuestionsID
);
You are passing PatientRiskAssessmentQuestionsID value to #PatientRiskAssessmentQuestionsID nvarchar(100) parameter
Then you are using it in next code
select 1 from PatientRiskAssessmentQuestionsList x
where x.NetworkRiskAssessmentListID = NetworkRiskAssessmentListID
and x.PatientRiskAssessmentQuestionsID = #PatientRiskAssessmentQuestionsID
so the issue in the AND condition, here
and x.PatientRiskAssessmentQuestionsID = 'PatientRiskAssessmentQuestionsID'
x.PatientRiskAssessmentQuestionsID is bigint
and #PatientRiskAssessmentQuestionsID is nvarchar (100)
its value
[PatientRiskAssessmentQuestionsID]
so fix this one, and everything will be Ok.
I have many tables that need ID scramblers, so:
CREATE PROCEDURE SP_generateUniqueID ( -- pass table here somehow -- )
AS
BEGIN
DECLARE #ID varchar(100) -- NEW ID.
DECLARE #isIDInUse tinyint -- BOOLEAN YES/NO.
SET #isIDInUse=1
WHILE(#isIDInUse=1) -- KEEP GENERATING TILL YOU FIND ONE:
BEGIN
SET #ID= dbo.generateID('aA1a1') -- GENERATES ID. doesn't matter how.
IF (#ID NOT IN (#passedTable)) -- DOES #ID EXIST ALREADY?
/*(SEARCHES THE PASSED TABLE! Which its size will be 1XN)*/
SET #isIDInUse=0 -- NO, YOU CAN USE.
END
RETURN #ID
END
I can't make the passing of the existing table go smoothly...
I want to be able to insert any table that uses IDs.
Any suggestion?
I would advise you REALLY look hard into better solutions for this issue. You will be hitting your table/index with every iteration of the new ID that you generate. What is wrong with an auto-incrementing integer value:
create table IDs (ID int identity(1,1))
(also, SQL Server has bit data types for boolean values. No need for your tinyint)
That aside, the only way I think you can do this your way is with dynamic SQL. Using the script below you should be able to see how you can pass in your schema.table to the stored procedure and within the procedure define your ID to be inserted in to the checking loop:
create table a(ID nvarchar(100)) insert into a values('1'),('2'),('3'),('4'),('5')
create table b(ID nvarchar(100)) insert into b values('6'),('7'),('8'),('9'),('10')
declare #Table nvarchar(100) = 'dbo.a'
declare #ID nvarchar(100) = '6'
declare #IDinUse bit = 0
declare #sql nvarchar(max) = 'if exists(select ID from ' + #Table + ' where ID = #ID) select #IDinUse = 1 else select #IDinUse = 0'
exec sp_executesql #sql, N'#ID nvarchar(100), #IDinUse bit output', #ID = #ID, #IDinUse = #IDinUse output
select #IDinUse as IDinUse
go
declare #Table nvarchar(100) = 'dbo.b'
declare #ID nvarchar(100) = '6'
declare #IDinUse bit = 0
declare #sql nvarchar(max) = 'if exists(select ID from ' + #Table + ' where ID = #ID) select #IDinUse = 1 else select #IDinUse = 0'
exec sp_executesql #sql, N'#ID nvarchar(100), #IDinUse bit output', #ID = #ID, #IDinUse = #IDinUse output
select #IDinUse as IDinUse
I am writing a procedure in SQL Server to insert or update records.
The update part of the code is working fine but when I am executing it for inserting, duplicate entries are inserted into the table.
I created the primary key to avoid this error but after creating that I am not able to insert any single record.
Here is the code :
Alter Procedure test_case
#id int,
#name nvarchar(20)
AS
If exists (Select t_id from testing2 where t_id = #id)
begin
update testing2
set t_id = #id, t_name = #name
where t_id = #id
end
else
begin
insert into testing2 (t_id, t_name, last_date, hard)
select
#id, #name, convert(date, getdate()), 'null'
from test
end
On executing it is showing 2 rows affected
You do not require test table in the select query
insert into testing2 (t_id, t_name, last_date, hard)
select
#id as t_id, #name as t_name, convert(date, getdate()) as last_date, 'null' as hard
is enough
I like to break functionality into smaller parts because it helps me to manage code better.
Maybe this is not a good example since it is pretty simple but I will write it anyway.
Create Procedure Testing2_InsertData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
Insert Into testing2
(t_id, t_name, last_date, hard)
Values
( #id, #name, GetDate(), null )
Go
Create Procedure Testing2_UpdateData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
Update testing2 Set
t_name = #name --, maybe last_date = GetDate()
Where ( t_id = #id )
Go
Create Procedure Testing2_SaveData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
If ( Exists( Select t_id From testing2 Where ( t_id = #id ) ) )
Exec Testing2_UpdateData #id, #name
Else
Exec Testing2_InsertData #id, #name
Go
I have a scenario wherein i have to execute an SP for specified number of time(number of execution will be mentioned by user) without using loop.
My SP is setting an OUTPUT variable of varchar type. I am willing to insert the output of my SP into a temp table and use it for further processing.
I am unable to modify this SP into function as it contain an Update statement.
Kindly suggest if we can do so without loop.
Whit this solution you do not need an output; #res is your result directly set in a temp table.
CREATE PROCEDURE [dbo].[myStoredProc]
#Counter int,
#params nvarchar(64),
#CreateTable bit
AS
DECLARE #res varchar(64)
IF #CreateTable = 1
BEGIN
IF EXISTS (SELECT 1 FROM dbo.sysobjects WHERE id = object_id(N'[#tempTable]'))
DROP TABLE #tempTable
CREATE TABLE #tempTable ([Res] [nvarchar] (64))
END
SET #res = CONVERT(varchar(64), #Counter)
SET #Counter = #Counter - 1
IF #Counter > 0
exec myStoredProc #Counter, #params, 0
INSERT #tempTable VALUES (#res)
IF #CreateTable = 1
BEGIN
SELECT * FROM #tempTable
DROP TABLE #tempTable
END
GO
DECLARE #o varchar(64)
exec [myStoredProc] 5, '', 1
I am using Dynamic SQL to retrieve datasets from multiple tables in order to monitor our daily data extraction from the iSeries system.
I have the below dynamic SQL code which works fine, but I want to only run the data to get each tables records if data has been extracted for the day
-- Create a table variable to store user data
DECLARE #myTable TABLE
(
docID INT IDENTITY(1,1),
docRef VARCHAR(50),
letterDir VARCHAR(500)
);
insert #myTable select docRef, saveDir from alpsMaster.dbo.uConfigData
-- Get the number of rows in the looping table
DECLARE #RowCount INT, #SQL nvarchar(500), #LoopSQL nvarchar(2000), #Date varchar(20)
set #Date='29 Oct 2013'
SET #RowCount = (SELECT COUNT(docID) FROM #myTable)
-- Declare an iterator
DECLARE #I INT
-- Initialize the iterator
SET #I = 1
-- Loop through the rows of a table #myTable
WHILE (#I <= #RowCount)
BEGIN
-- Declare variables to hold the data which we get after looping each record
DECLARE #docRef VARCHAR(10), #saveDir VARCHAR(500)
-- Get the data from table and set to variables
SELECT #docRef = docref FROM #myTable WHERE docID = #I
SELECT #saveDir = letterDir FROM #myTable WHERE docID = #I
-- Display the looped data
--PRINT 'Row No = ' + CONVERT(VARCHAR(2), #I) + '; docRef = ' + #docRef
select #LoopSQL='
use alpsProduction;
declare #SQL nvarchar(500);
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(''[dbo].['+#docRef+']''))
begin
if exists(select * from sys.columns
where Name = ''YPTMPID'' and Object_ID = OBJECT_ID(''[dbo].['+#docRef+']''))
begin
set #SQL=''SELECT t.template_name,'''''+#saveDir+''''', Y.*
FROM [alpsProduction].[dbo].'+#docRef+' Y, alpsMaster.dbo.uDocumentTemplates t
where DTEINP='''''+#Date+''''' and t.template_Id=y.YPTMPID and t.docRef='''''+#docRef+'''''''
exec sp_executesql #SQL
end
end
'
--print #LoopSQL
exec sp_executesql #LoopSQL
-- Increment the iterator
SET #I = #I + 1
END
so I tried using
IF ##ROWCOUNT >0
Begin
exec sp_executesql #SQL
end
but it seems to never populate the ##Rowcount.
Whats the best way to only run that statement (exec sp_executesql #SQL) if the current table (identified by #docRef) has records in it for todays date (in the format dd mmm yyyy)
Create job to execute a sql script in which u must check inserted data on current day then execute your sp. like this.
IF EXISTS ( SELECT * FROM #TABLE T WHERE DATEDIFF(DD, GETUTCDATE(), T.CREATEDON) = 0 )
BEGIN
EXEC SP_EXECUTESQL #SQL
END