Many times i found myself in trouble ( Beatles ???) when i needed to change sql tables design based on some conditional logic so i couldn’t use Insert Select technique simply because it doesn’t support if statements when i needed something beyond when condition abilities.
real life example :
problem i faced lately was relationship icons near each profile for community website when users had a relationships (ie. sent messages), messages were stored in “Messages” table and my requirement was to show near each user’s profile whether logged user had a relationship with them and what kind. So you could say just have a JOIN between “Users” and “Messages” sql tables but first of i had 4 kinds of relationships and second of all think what kind of optimization would it be to have even one JOIN between two tables with more than hundreds of thousands records each. This ain’t working unless you are ready to buy super servers to store databases on. You could also say create a function that checks for each returned from query user what kind of relationship logged user has with which is fine but i this way i would have many double records like UserA and UserB could have messaged each other, added to friend or blacklist.
So the idea was to create a Relationships sql table which holds User1,User2,Relationship1,Relationship2,Relationship3,Relationship4. When any Relationship column was an integer “0” for no relationship, 1 for User1’s action, 2 for User2’s action and 3 for mutual action ( both users messaged each other).
You can say now cool, this what i should do in the first place but if you work on website optimization like i did? What if you are not the original designer?
Now what ? Problem is that there is a message record for each message sent between users so every time message was sent the sender was User1 and the receiver was User2 which created lots of records for single relationship when i needed create one field that contains all the relationships between two users. This where for statement comes handy. First of all i created a stored procedure that had a conditional logic, checked if there is a relationship between users and then updated or inserted upon request. Now all i need is a for loop though Messages table so it will send User1 and User2 to my stored procedure, this is where cursors came to save me because otherwise i would be needed to create C# function to make the conditional logic which would be many times slower. Cursors are not advisable for real time results as well simply because they are very slow and CPU demanding compared to more elegant solutions in sql or just proper design but in off-line changes like these i could allow to have cursor for loop but again the are much faster than C# accessing the database and manipulating it.
here is the code
code :
-- setting nocount on so the query will be faster as won't return number of rows affected set nocount on -- declaration of two int variables which will hold current userID's declare @userA int, @userB int --declaration of the cursor that will loop though table in it's declaration declare cur cursor for select fieldA,fieldB from tableA -- opening cursor open cur -- get first result from table fetch next from cur into @userA ,@userB -- loop until there are no rows left while @fetch_status = 0 begin -- stored procedure with current userIDs exec someStoredProcedure @userA ,@userB -- get next result fetch next from cur into @userA ,@userB end -- closing cursor close cur -- removing it from sql server memory deallocate cur
Tags: sql