Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Dynamically create cursors

Author  Topic 

IceCreamWizard
Starting Member

11 Posts

Posted - 2007-11-15 : 16:25:22
I'm developing reports and custom utilities on a third party application database. The application manages different cases (bunch o' info). For each case, it creates about 24+ tables with unique names based on the case number. (Editorial comment: The creators of this application have never heard of the word normalization, but I digress...)
So, for my utilities I want to create generic stored procedures that accepts the case number as a parameter. From that, I dynamically create T-SQL commands in a variable (eg, @query) and execute them via 'exec sp_executesql @query [optional params]'. So far, I've been successful in making this happened.
However, for my latest utility, I need to dynamically create a cursor. For example...

set @myCursor = cursor for
select Col3 from Case4_TableA
where Col2 is not null;

Clearly that is hard coded. What I want is something like this...

set @query = 'cursor for
select Col3 from Case + ' @caseID + '_TableA
where Col2 is not null';
exec @myCursor = @query

When I try that the error is (something like) "A cursor variable is not allowed in this context."

Any help would be appreciated! Thank you!

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2007-11-15 : 16:39:45
Why do you even want to use a cursor in the first place? Have you made sure that a set-based solution wasn't available in the first place?

Is performance even a concern for you?

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

IceCreamWizard
Starting Member

11 Posts

Posted - 2007-11-15 : 16:43:22
Yes, a cursor is the only way to go. I need to update two tables based on information in two other tables. Also, I need to do string manipulation based on values and null entries, etc. before I update/insert the tables.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2007-11-15 : 16:52:41
What you have described does not require cursors. Please show us a data example so that we can help write the correct solution.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

IceCreamWizard
Starting Member

11 Posts

Posted - 2007-11-16 : 08:20:36
Okay, here goes, I'll give it my best shot to describe this. There are four tables involved. (Reminder: This is a third party application. I can add tables and columns but I cannot restructure what is there.)

Tables

  • tKeyword: Contains a list of keywords that must be identified in the document text table (tDocText). Has status column (called font=Courier New]status[/font=Courier New]) that needs to be updated upon successful processing.

  • tDocs: A table that holds information (attributes and metadata) about documents. One of its columns is updated. We'll call this column attribute1 and it is an ntext datatype. This column may hold zero or more values with each value delimited by HTML-style tags. For example: <tag>Val1</tag> <tag>Val2</tag>

  • tTextDocs: A table that holds the text (OCR) of the documents listed in tDocs. The text is held in an ntext column (called theText). In this problem, this table is only read from.

  • tDocs_attribute1: This table holds an entry for every value in the docAttribute1 column of the tDocs table. Its columns are DocID, SequenceNumber, Term. TableFk is the reference to the entry in the tDocs table; SequenceNumber is the zero-based number of the value in the docAttribute1 column; and Term is the value (eg, Val1) in the column. However, in this Term column, the value is not delimited by tags.


Sample Data

tKeyword
id keyword status
1 FooBar {null}
2 George {null}
3 Frank {null}
tDocs
id title attribute1
10 Meeting Minutes <tag>FooBar</tag> <tag>George</tag> <tag>Frank</tag>
11 Sales call notes {null}
12 Project Proposal {null}
tTextDocs
id docID theText
20 10 '16 November 2007 Project FooBar Meeting In attendance...'
21 11 '16 November 2007 Called Company XYZ to discuss...'
22 12 '16 November 2007 Project Proposal Our company is...'
tDocs_attribute1
docID seqNum Term
10 0 FooBar
10 1 George
10 2 Frank

For document DocID=10, I've shown what the result of this task should be along with its associated entries in tDocs_attribute1.

If you're still reading this, you're a brave soul. So, given the above, here's the task:

Iterate through the entire tKeyword table for each entry in the tDocs table. If the keyword is found in the text of the document as found in the tTextDocs table, then add that keyword to the attribute1 column of the tDocs table and add a new entry in the tDocs_attribute1 table, making sure the seqNum is correct. As each keyword is processed, update the tKeyword status column with 'done'.

As you can quickly see, there is the cross product (for lack of a better term) with the tKeyword table and the tDocs table. Hence, currently, I have a nested cursor solution and it works.

What I want to do is to write a generic stored proc to make this happen rather than copy-paste-edit a new one for each case (see my original post) that is created in the database.

Whew! I think that's it. If you can provide a set-based, non-cursor solution, I'm all for it! Please share your insight. Thanks!
Go to Top of Page

Vinnie881
Master Smack Fu Yak Hacker

1231 Posts

Posted - 2007-11-16 : 22:09:10
Let me know if you have any issues.


/*
-- Create Function to add the keywords to the attribute line
CREATE FUNCTION dbo.ConcatKeywords(@DocID int)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = '<tag>' + b.Term + '</tag>'
FROM TDocs_Attribute1 a
WHERE a.DocID = @DocID
ORDER BY a.SeqNum

RETURN @Output
END
*/

/*Below will add every keyword that exists for a particular docID into TDocs_Attribute1.

Note: you may want to add a where clause below to filter to make sure that keyword wasn't already added from a previous run.
*/

Insert Into TDocs_Attribute1(
DocID
,Term
,SeqNum
)
Select a.DocID
,b.KeyWord
,Coalesce((select count(*) from TDocs_attribute1 aa where aa.DocID = a.DocID),0) + Row_Number() over (Partition by a.DocID order by b.id) - 1
from
tTextDocs a
inner join
tKeyWord b
on a.TheText like '%' + b.Keyword + '%'


--Updates all the DocID attributes using the function you created
Update a
set a.Attribute = dbo.ConcatKeywords(a.ID)
From
tDocs a

Go to Top of Page
   

- Advertisement -