BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
buechler66
Barite | Level 11

Hi. In the code below I'm reading in a Proc Sql query using the DATALINES statement to a variable named USER_SQL.  I'm then trying to update the USER_SQL variable to put '/*' and '*/' around the Create Table statement.  Basically I'm trying to comment out the Create Table statement.

 

I'm having two problems in the second datastep below:

1.  CRT_TBL_STTMNT = SUBSTR(USER_SQL, INDEX(USER_SQL,'CREATE TABLE'), INDEX(USER_SQL,' AS')+2);

This statement is extracting too many characters.  I want it to pull just 'CREATE TABLE OUT.MYTAB AS', but instead it's pulling 'CREATE TABLE OUT.MYTAB AS SELECT DISTINCT'.  I can't figure out why.

 

2.  USER_SQL = TRANWRD(USER_SQL, CRT_TBL_STTMNT, NEW_CRT_TBL_STTMNT);

I'm trying to replace the current Create Table statement inside the USER_SQL variable with the new Create Table statement that has  the Comment signs around it, but it's failing to make the replacement.

 

If you have time to take a look the code you can run is:

DATA USER_SQL;
  INFILE DATALINES EOF=WRITE;
  LENGTH USER_SQL $32767 ;  
  RETAIN USER_SQL;
  INPUT;
  USER_SQL=CATX(' ',USER_SQL,_INFILE_);
RETURN;
WRITE: OUTPUT;
DATALINES4;

PROC SQL;
CREATE TABLE OUT.MYTAB AS
SELECT DISTINCT 
		CLM.BENE_SK
		,1 as card
FROM	OPI_AAL.CLM AS CLM
INNER JOIN NFPP_TRD.&SYSUSERID._HHASWITCH_CLMS AS HHACLMS
	ON CLM.BENE_SK = HHACLMS.BENE_SK
WHERE (CLM.CLM_FROM_DT BETWEEN &bgn_dt AND &end_dt) 
	AND (CLM.CLM_PRNCPL_DGNS_CD LIKE 'I50%' or CLM.CLM_DGNS_1_CD LIKE 'I50%' or CLM.CLM_DGNS_2_CD LIKE 'I50%' 
     			or CLM.CLM_DGNS_3_CD LIKE 'I50%' or CLM.CLM_DGNS_4_CD LIKE 'I50%' or CLM.CLM_DGNS_5_CD LIKE 'I50%' 
				or CLM.CLM_DGNS_6_CD LIKE 'I50%' or CLM.CLM_DGNS_7_CD LIKE 'I50%' or CLM.CLM_DGNS_8_CD LIKE 'I50%')
	AND CLM.CLM_FINL_ACTN_IND = 'Y'
	AND CLM.CLM_TYPE_CD BETWEEN 2000 AND 2999
order by BENE_SK
;QUIT;
;;;;

DATA USER_SQL2;
SET USER_SQL;

IF FIND(USER_SQL,'CREATE TABLE') = 0 THEN CRT_TBL_IND=0; ELSE CRT_TBL_IND=1;
IF CRT_TBL_IND=1 THEN DO;
	/* PULL OUT THE CREATE TABLE STATEMENT */
	CRT_TBL_STTMNT = SUBSTR(USER_SQL, INDEX(USER_SQL,'CREATE TABLE'), INDEX(USER_SQL,' AS')+2);
	/* APPEND SAS COMMENT MARKERS AROUND THE CREATE TABLE STATEMENT */
	NEW_CRT_TBL_STTMNT = CATX(' ', '/* ',SUBSTR(USER_SQL,INDEX(USER_SQL,'CREATE TABLE'),INDEX(USER_SQL,' AS')+2),' */');
	/* REPLACE THE EXISTING CREATE TABLE STATEMENT WITH THE COMMENTED VERSION */
	USER_SQL = TRANWRD(USER_SQL, CRT_TBL_STTMNT, NEW_CRT_TBL_STTMNT);
END;
RUN;


 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

SUBSTR (target, startcharacter, NUMBEROFCHARACTERS) not position

 

DATA USER_SQL2;
SET USER_SQL;

IF FIND(USER_SQL,'CREATE TABLE') = 0 THEN CRT_TBL_IND=0; ELSE CRT_TBL_IND=1;
IF CRT_TBL_IND=1 THEN DO;
	/* PULL OUT THE CREATE TABLE STATEMENT */
   createpos = INDEX(USER_SQL,'CREATE TABLE');
   ASpos =INDEX(USER_SQL,' AS');
	CRT_TBL_STTMNT = SUBSTR(USER_SQL,createpos,(aspos-createpos) +3);
END;
RUN;

View solution in original post

8 REPLIES 8
Tom
Super User Tom
Super User

How "nice" is your SQL code?

You might have better luck leaving the code broken into individual lines instead of smushing it together into a single string.

Then your searches for PROC SQL and CREATE statements can be much easier (assuming that code is following some minimal formatting standards).

 

if left(upcase(line)) =: 'PROC SQL' and not findw(line,'noexec',,'sit') then do;
  loc=index(line,';');
  if loc then line=catx(' ',substr(line,1,loc-1),'noexec',substr(line,loc));
  else line=catx(' ',line,'noexec');
end;
if left(upcase(line))=:'CREATE TABLE' then do;
  line=cats('*',line,';');
end;
buechler66
Barite | Level 11

Unfortunately it's going to be code from today to code from 10 years ago - and from hundreds of different users to boot.

Do you see any reason why this statement is pulling too many characters? It seems straight forward enough.  I don't get it.

CRT_TBL_STTMNT = SUBSTR(USER_SQL, INDEX(USER_SQL,'CREATE TABLE'), INDEX(USER_SQL,' AS')+2);

ballardw
Super User

SUBSTR (target, startcharacter, NUMBEROFCHARACTERS) not position

 

DATA USER_SQL2;
SET USER_SQL;

IF FIND(USER_SQL,'CREATE TABLE') = 0 THEN CRT_TBL_IND=0; ELSE CRT_TBL_IND=1;
IF CRT_TBL_IND=1 THEN DO;
	/* PULL OUT THE CREATE TABLE STATEMENT */
   createpos = INDEX(USER_SQL,'CREATE TABLE');
   ASpos =INDEX(USER_SQL,' AS');
	CRT_TBL_STTMNT = SUBSTR(USER_SQL,createpos,(aspos-createpos) +3);
END;
RUN;
buechler66
Barite | Level 11
Ugh! Stupid, stupid, stupid. Thank you so much.
ballardw
Super User

@buechler66 wrote:
Ugh! Stupid, stupid, stupid. Thank you so much.

I know at least one programming language where there are two forms of substr

 

substr(string,start position , end position)

substr(string,start position ; length)

the delimiter between the start and end/length tells the function which one to do. WARNING: I may have the examples backwards as far as end position vs length but I think the point is valid.

 

And if you think that approach may have lead to some code frustration you are absolutely right.

ChrisNZ
Tourmaline | Level 20

@ballardw  I wish SAS had this option. Maybe using a fourth parameter.

ballardw
Super User

@ChrisNZ wrote:

@ballardw  I wish SAS had this option. Maybe using a fourth parameter.


Maybe time for Ballot box suggestion.

ChrisNZ
Tourmaline | Level 20

> Maybe time for Ballot box suggestion.

@ballardw I have proposed countless ideas there! Dozens I think. And not only there, here and here too.

They seem to be gathering dust rather nicely.

sas-innovate-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 1297 views
  • 4 likes
  • 4 in conversation