April 20, 2006 at 7:26 am
Does anyone know how to pass a where clause into a stored procedure?
for example ;
create procedure sp_load_documents_into_folder
@keywordlist nvarchar(4000),
@conditions nvarchar(4000) = NULL
as
declare @tablevar table(keyword varchar(9))
declare @documentnumber int, @foldernumber int, @foldername varchar(50)
set @foldername = 'temp folder' + cast((rand() *100000) as varchar(7))
insert into folders (foldername, createdate) VALUES (@foldername, GETDATE() )
insert into @tablevar select str from iter_charlist_to_table(@keywordlist, DEFAULT)
If @conditions <> Null
BEGIN
DECLARE docinsert CURSOR FAST_FORWARD for
select distinct dn.documentnumber from docnumbers dn (nolock)
inner join DocKeywords dk (nolock) on dk.documentnumber = dn.documentnumber
inner join @tablevar tv on tv.str = dk.keyword_value
where @condition and dn.docdeleted = 0
OPEN docinsert
fetch next from docinsert into @documentnumber
while @@fetch_status =0
BEGIN
insert into folder_items (workspaceid, folderid, documentid) VALUES (@folderid, 0,@docid)
fetch next from docinsert into @documentnumber
END
CLOSE docinsert
DEALLOCATE docinsert
END
ELSE
BEGIN
DECLARE docinsert CURSOR FAST_FORWARD for
select distinct dn.documentnumber from docnumbers dn (nolock)
inner join DocKeywords dk (nolock) on dk.documentnumber = dn.documentnumber
inner join @tablevar tv on tv.str = dk.keyword_value
where dn.docdeleted = 0
OPEN docinsert
fetch next from docinsert into @documentnumber
while @@fetch_status =0
BEGIN
insert into folder_items (workspaceid, folderid, documentid) VALUES (@folderid, 0,@docid)
fetch next from docinsert into @documentnumber
END
CLOSE docinsert
DEALLOCATE docinsert
END
I would want to exec the sp as
exec sp_load_documents_into_folder 'abc,def,abd,dek,gcc',"dn.documentnumber > 50"
which would should insert rows into the folder_items table where the documentnumber is greater than 50.
This does not work and returns an error of incorrect syntax near and on the "Where @condition and ..." line.
Does anyone know what to do to rememdy this?
April 20, 2006 at 7:32 am
For dynamic SQL you'll need to use the exec command and treat the whole statement as a concatenanted string.
See:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_ea-ez_05ro.asp
April 20, 2006 at 7:41 am
Exec robs me of the ability to share variables between the sp and the EXEC.
Am I missing something?
April 20, 2006 at 8:01 am
What do you mean by "robs me"?
It should be as simple as this:
declare @sqlstring varchar(500)
set @sqlstring = 'update sql code where '+@wherevar+'rest of sql code'
exec (@sqlstring)
April 20, 2006 at 8:14 am
exec doesnt understand the table variable and wants me to declare it. Its assuming its a local.
April 20, 2006 at 9:01 am
Try using a temp table instead of a table variable.
I just did a real simple test and it worked.
Here's my quickie code:
select *
into #tmptest
from test_table
declare @sqlstr varchar(200)
set @sqlstr = 'select * from #tmptest'
exec (@sqlstr)
April 20, 2006 at 9:12 am
It still doesnt like it. Can you try adding the @conditions into your test and see if yuo get the same result. It may be something I am stupidly typing.
Server: Msg 245, Level 16, State 1, Procedure sp_load_workspace_for_publishing, Line 41
Syntax error converting the varchar value 'DECLARE docinsert CURSOR FAST_FORWARD for...
April 20, 2006 at 10:03 am
Hmmm, that cursor complicates things. Not sure of the error you're getting or why (whould have to see your code).
However, what you might want to do is run the select into (another) temp table and then declare your cursor on select * from the new temp table.
So it would be...
--do code to prep data into first temp table
declare @sqlstr varchar (500)
set @sqlstr = 'select whatever into #tmp2 where'+@where+'whatever else'
exec (@sqlstr)
DECLARE docinsert CURSOR FAST_FORWARD for
select * from #tmp2
open docinsert
---
Totaly untested and theoretically speaking, of course.
The other thing, and truly the recommended approach, would be to refactor this code so that you don't use cursors. If you've read anything around here, you know that cursors are (generally speaking) to be avoided.
Alternatively, unless that "where" clause has to be completely configurable (which since you're doing an update is a big red flag). you might want to look at having a case / if switch with canned SQL rather than using dynamic SQL.
April 20, 2006 at 10:11 am
If you know of a way to eliminate the need for a cursor in this situation, that would be AWSOME. I havent figured out any way to get around it in this situation where I have to insert multiple rows with some common and some changing values.
I'll hack at it and see if I can figure something out.
Thanks for your Help Pam.
April 20, 2006 at 10:30 am
Well. I'm trying but this isn't making any sense to me:
select distinct dn.documentnumber from docnumbers dn (nolock)
inner join DocKeywords dk (nolock) on dk.documentnumber = dn.documentnumber
inner join @tablevar tv on tv.str = dk.keyword_value
where @condition and dn.docdeleted = 0
OPEN docinsert
fetch next from docinsert into @documentnumber
while @@fetch_status =0
BEGIN
insert into folder_items (workspaceid, folderid, documentid) VALUES (@folderid, 0,@docid)
Is @documentnumber supposed to be @docid?
Also it looks to me (from names) that it should be values(0,@folderid,@docid).
Give me a clear example and I should be able to come up with a way to eliminate the cursor.
April 20, 2006 at 11:09 am
My god the timeout on the message board is annoying. You cant even go back to recover what you have typed.
The folder items column list should be (folderid, nodeid, documentnumber)
all references to docid should be documentnumber. I was sloppy when obfuscating the example.
I used what you said in a two stage process instead of one lump and was able to get it to work ; selecting the @tablevar into a temp table and then using it in the EXEC to extract the documentnumbers into another temp table, and then using that second temp table to run the cursor against allowed me to do what I was trying to achieve.
I would still be interested to at least in concept know how to replace cursors for this kind of data inserts, if you would be willing to explain.
Thanks for your help Deb!
April 20, 2006 at 11:45 am
Here's a starting point for you:
create table #tmpfolder_items
(folderid int, nodeid int, documentid int)
create table #tmpdn
(documentnumber int, docdeleted int)
create table #tmpdkw
(documentnumber int,keyword_value varchar(20), docwhere int)
create table #tmptablevar
(str varchar(20))
declare @folderid int
set @folderid = 1
insert into #tmpfolder_items
(folderid, nodeid, documentid)
--VALUES
select distinct
@folderid,
0,
dn.documentnumber
from
#tmpdn dn
INNER JOIN
#tmpdkw dk
on
dk.documentnumber = dn.documentnumber
INNER JOIN
#tmptablevar tv
on
tv.str = dk.keyword_value
where
dk.docwhere > 2
and
dn.docdeleted = 0
drop table #tmpfolder_items
drop table #tmpdn
drop table #tmpdkw
drop table #tmptablevar
April 21, 2006 at 7:19 am
This error, somewhat erroneously reported as a "Syntax error":
....Server: Msg 245, Level 16, State 1, Procedure sp_load_workspace_for_publishing, Line 41
Syntax error converting the varchar value 'DECLARE docinsert CURSOR FAST_FORWARD for........
Is what you get when you try to concatenate a string value and an integer. In this case, it is not complaining about the syntax of the SQL expression, but rather the values that are in the concatenation operation. The implicit conversion goes from varchar to int when mixing the two types, so you need to make sure that the int is cast to varchar.
select 'a' + 1 will give you the same "syntax error" even thought it is not really a SQL syntax error, but rather an error in the data.
IOW, find the uncast int, and that might fix your problem.
jg
April 21, 2006 at 7:25 am
5 casts added to that method resulted in no more syntax error and a second working method. Thanks Jeff!
April 21, 2006 at 8:14 am
Nobody pointed out to this poor soul that
if @conditions Null
won't work...
Viewing 15 posts - 1 through 15 (of 15 total)
You must be logged in to reply to this topic. Login to reply