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
 General SQL Server Forums
 New to SQL Server Programming
 Basic SQL substitution question

Author  Topic 

sixsigma1978
Starting Member

25 Posts

Posted - 2011-08-17 : 14:35:34
All - I have a script that tends to repeat there where clause over and over again and was wondering if there was some way for me to substitute the parameters of the where clause.


update T1 set C1="xx" where C2 in (1, 2, 3, 4, 5);
update T2 set C3="yy", C4="zz" where C2 in (1, 2, 3, 4, 5);
....


As you can see the IN (1, 2, 3, 4, 5); repeats multiple times - and was wondering If I could use a DECLARE TYPE statement or something equivalent to substitute it at the beginning of the script, thus:


DECLARE TYPE some_var (1,2,3,4,5);
BEGIN
update T2 set C3="yy", C4="zz" where C2 in (some_var);
END;


IS there anything similar in SQL?

Kristen
Test

22859 Posts

Posted - 2011-08-17 : 15:59:51
I would put the "list" 1,2,3,4,5... into a temporary table and then JOIN that to T1 and T2 to restrict the data set.

That only works for your particular example using the IN statement, so may not be appropriate for more general cases.

You could use dynamic SQL - that would require that the "C2" column name, in your example, was consistently use on all tables T1, T2, ...

Using parameter substitution (e.g. using sp_ExecuteSQL) this would be a highly performant solution, although there would be Permissions issues which would be more complicated to solve than using a Stored Procedure and granting it EXECUTE permission.
Go to Top of Page

sixsigma1978
Starting Member

25 Posts

Posted - 2011-08-17 : 16:15:02
Thanks Kirsten - however, after googling (and a bit of plagiarizing :) )
I found an interim solution- this seems a bit complex - but looks like the trick is in getting the parser function right!!


CREATE OR REPLACE FUNCTION Split
(
PC$Chaine IN VARCHAR2, -- input string
PN$Pos IN PLS_INTEGER, -- token number
PC$Sep IN VARCHAR2 DEFAULT ',' -- separator character
)
RETURN VARCHAR2
IS
LC$Chaine VARCHAR2(32767) := PC$Sep || PC$Chaine ;
LI$I PLS_INTEGER ;
LI$I2 PLS_INTEGER ;
BEGIN
LI$I := INSTR( LC$Chaine, PC$Sep, 1, PN$Pos ) ;
IF LI$I > 0 THEN
LI$I2 := INSTR( LC$Chaine, PC$Sep, 1, PN$Pos + 1) ;
IF LI$I2 = 0 THEN LI$I2 := LENGTH( LC$Chaine ) + 1 ; END IF ;
RETURN( SUBSTR( LC$Chaine, LI$I+1, LI$I2 - LI$I-1 ) ) ;
ELSE
RETURN NULL ;
END IF ;
END;


CREATE OR REPLACE FUNCTION Dynamic_In ( PC$list IN VARCHAR2 )
RETURN sys.dbms_debug_vc2coll
IS
ttab sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll() ;
LC$Token VARCHAR2(100) ;
i PLS_INTEGER := 1 ;
BEGIN
-- Populate the collection --
LOOP
LC$Token := Split( PC$List, i , ',') ;
EXIT WHEN LC$Token IS NULL ;
ttab.extend ;
ttab(ttab.COUNT) := LC$Token ;
i := i + 1 ;
END LOOP ;
RETURN ttab ;
END ;

BEGIN
DECLARE LC$List Varchar2(100) := '1, 2, 3';
update T set C1='xx' where C2 in (SELECT * FROM TABLE( CAST ( Dynamic_In(LC$List) AS sys.dbms_debug_vc2coll ) ) );

END;
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2011-08-17 : 16:34:41
That's for Oracle by the looks of it.

If you just have an IN list then, yes, a SPLITTER function that puts the values into a temporary table (or a function representing a table) will do nicely

if you are using SQL Server there was some discussion about various flavours of making a Splitter Function in this thread:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648
Go to Top of Page

sixsigma1978
Starting Member

25 Posts

Posted - 2011-08-18 : 09:41:21
Yes - that is an oracle version of the split function - I was battling to convert it to the SQL Server semantics - your link is very helpful!! thanks !
Go to Top of Page
   

- Advertisement -