September 21, 2004 at 4:12 am
HI
I am using the SQL code below to return a list of contacts associated with a page. During testing the @LearnID was set to 2. This returned any records where there is only one value in puTOP_SECTIONID field = 2. The problem is when there is multiple values in the field, such as when it contains "8,10,2,4", it doesn't return that record even though 2 is in it. puTOP_SECTIONID is a char(100) field.
Anyone know a workaround I could use?
Thanks all.
Brendan
CREATE PROCEDURE spGetLearnImproveContactsByID
@LearnID char(100)
AS
Begin
SELECT rtrim(REGION) As REGION, rtrim(CONTACT_NAME) As CONTACT_NAME, rtrim(TELEPHONE) As TELEPHONE, rtrim(CONTACT_EMAIL) AS CONTACT_EMAIL, CONTACT_ORDERBY
FROM TBLCONTACT, TBLREGION
WHERE TBLCONTACT.puTBLREGION = TBLREGION.puTBLREGION And @LearnID IN (puTOP_SECTIONID)
ORDER BY CONTACT_ORDERBY, REGION, CONTACT_NAME
End
GO
September 21, 2004 at 5:04 am
What you're asking for is how to tokenize the input variable. Not easily done in Transact SQL, and tend to get pretty ugly when attempted. It's not optimal and don't scale well.
One technique is to parse the input variable, look for the breaker charachters (comma?) and one by one store the values in a temptable. Then rewrite the select query to join against the temptable instead of using the IN clause..
Not easy, not pretty, slow and ugly but it can be done.
Another option is to not accept a string of several arguments in the same variable. (it's a design issue - don't design this way)
In any case, good luck
/Kenneth
September 21, 2004 at 5:04 am
Hi Brendan,
The reason it fails is that the puTOP_SECTIONID is treated as a single value of "8,10,2,4" and not individual values of 8, 10, 2, 4.
The IN clause is really just a short cut for multiple OR statements.
These statement are the same to SQL.
SELECT region FROM table WHERE field = 1 OR field = 2
SELECT region FROM table WHERE field IN ( 1, 2 )
To achive what you want I would use Dynamic SQL, but the downside is that the performance will be affected. How much will depend on the size of the table etc.
CREATE PROCEDURE spGetLearnImproveContactsByID
@LearnID char(100)
AS
Begin
DECLARE @SQL VARCHAR(1000)
SELECT "SELECT rtrim(REGION) As REGION, rtrim(CONTACT_NAME) As CONTACT_NAME, rtrim(TELEPHONE) As TELEPHONE, rtrim(CONTACT_EMAIL) AS CONTACT_EMAIL, CONTACT_ORDERBY"
+ "FROM TBLCONTACT, TBLREGION"
+ "WHERE TBLCONTACT.puTBLREGION = TBLREGION.puTBLREGION And @LearnID IN (" + puTOP_SECTIONID + ")"
+ "ORDER BY CONTACT_ORDERBY, REGION, CONTACT_NAME"
EXECUTE(@SQL)
End
GO
Regards
Richard.
September 21, 2004 at 5:48 am
Have made a seperate table which now links the section to the Contact, but
am now having trouble inserting into this table using SQL. The code I have
(simplified) is:
Declare @ContactID bigint
--Insert contact details into Contact table
insert into [TBLCONTACT] (ContactName)
values (rtrim(@Name))
--Retrieve id of inserted contact
Set @ContactID = @@IDENTITY
--insert into table linking Contact to Section
insert into [TBLCONTACT_TO_TBLSECTION] puTBLCONTACT, puTBLTOP)
values (@ContactID, @Section)
What I need is to loop the last two lines of SQL so that a new record is
inserted for each value passed in the @Section parameter. So if @Section
contained "3,8,10" Then it would insert 3 records.
Any ideas?
Brendan
September 21, 2004 at 7:45 am
You could use this in the where clause
CHARINDEX(',' + CAST(@LearnID as varchar) + ',',',' + puTOP_SECTIONID) + ',') > 0
but you will sacrifice performance
Far away is close at hand in the images of elsewhere.
Anon.
September 21, 2004 at 7:51 am
The following will anser you last question
WHILE CHARINDEX(',',@Section) > 0
BEGIN
insert into [TBLCONTACT_TO_TBLSECTION] puTBLCONTACT, puTBLTOP)
values (@ContactID, LEFT(@Section,CHARINDEX(',',@Section)-1)
SET @Section = SUBSTRING(@Section,CHARINDEX(',',@Section)+1,LEN(@Section))
END
insert into [TBLCONTACT_TO_TBLSECTION] puTBLCONTACT, puTBLTOP)
values (@ContactID, @Section)
Far away is close at hand in the images of elsewhere.
Anon.
September 22, 2004 at 4:37 am
Apart from anything else, your clause '@LearnID IN (puTOP_SECTIONID)' is the wrong way round. The IN clause works like 'needle IN haystack'. Try rewriting it as 'puTOP_SECTIONID IN (@LearnID)'.
The SP is also intrinsically open to SQL Injection attacks if it is coded as shown. Have a look in the forums for SQL Injection for tips on what the security issues with this are and how to avoid it.
Original author: https://github.com/SQL-FineBuild/Common/wiki/ 1-click install and best practice configuration of SQL Server 2019, 2017 2016, 2014, 2012, 2008 R2, 2008 and 2005.
When I give food to the poor they call me a saint. When I ask why they are poor they call me a communist - Archbishop Hélder Câmara
September 22, 2004 at 4:42 am
Hi
Thanks to all for your help. I have managed to take something from each reply to get the problem sorted.
Brendan
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply