I have a JCL with the following format
Proc Library
//JS020 EXEC PGM=IKJEFT01,
// DYNAMNBR=20
//*
//EXTRACT DD DSN=PATH.EXTRACT,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,
// SPACE=(TRK,(1,10),RELEASE)
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSPUNCH DD SYSOUT=*
//*
//SYSTSIN DD DSN=PATH.CONTROL_CARD_LIB(CARD1), DISP=SHR
//SYSREC00 DD DSN=TABLEA.UNLOAD.FILE,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,LRECL=80
//SYSIN DD DSN=PATH.CONTROL_CARD_LIB(CARD2), DISP=SHR
----->>
PATH.CONTROL_CARD_LIB
CARD1
DSN SYSTEM(XXXX)
RUN PROGRAM(DSNTIAUL) PLAN(DSNTIAUL) PARM('SQL')
CARD2
Select * from TABLE
where condition1
and condition2
and condition3
When I submit my job I am always getting SQLSTATE = 7003 and SQLCODE = -518. I tried looking in the web and got the following description
The statement identified in the EXECUTE statement is a select-statement, or is not in a prepared state.
Can someone tell me what I miss? Many thanks.
I think it could simply be you are missing a semi-colon ( ; ) to terminate your sql statement.
As James mentions, your SELECT statement in CARD2 is missing a semicolon. When you specify PARM('SQL'), it indicates that your input data set contains one or more complete SQL statements, each of which ends with a semicolon.
If you do not specify the SQL parameter, your input data set must contain one or more single-line statements (without a semicolon) that use the following syntax:
table or view name [WHERE conditions] [ORDER BY columns]
Each input statement must be a valid SQL SELECT statement with the clause SELECT * FROM omitted and with no ending semicolon.
Please refer to this for more details => http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2.doc.apsg%2Frntiaul.htm
Related
Getting error SQLCODE = -805, ERROR: DBRM OR PACKAGE NAME DALLAS9..DSNTIAUL.184FA79814E1838D NOT FOUND IN PLAN COBDBSTR.REASON 01.
//DBULOAD JOB CLASS=A,MSGCLASS=A,NOTIFY=&SYSUID,MSGLEVEL=(1,1),
// PRTY=15,REGION=4M
//*
//JOBLIB DD DSN=DSN910.DB9G.SDSNEXIT,DISP=SHR
// DD DSN=DSN910.SDSNLOAD,DISP=SHR
//UNLOAD EXEC PGM=IKJEFT01,DYNAMNBR=50
//SYSIN DD *
SELECT * FROM SYSIBM.SYSTABLES ;
/*
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(DSNTIAUL) -
PLAN(DSNTIAUL) -
LIB('DSN910.DB9G.RUNLIB.LOAD') -
PARMS('SQL')
END
/*
//SYSREC00 DD DSN=RAHUL.TABLE.UNLOAD,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,SPACE=(CYL,(1,1),RLSE)
//*** TABLE STRUCTURE
//SYSPUNCH DD DSN=RAHUL.TABLE.SYSPUNCH,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,SPACE=(CYL,(1,1),RLSE)
//*
I am running Db2 unload JCL and getting the above error. As per above error it is asking me to bind again. No idea where is DSNTIAUL dbrm module.
Getting same error again and again. It is a utility. My JCL completes with a 0012 error code . Please help guys.
You are running into DB2 Sql Error Code -805.
-805 PACKAGE NAME location-name.collection-id.dbrm-name.consistency-token NOT FOUND IN PLAN plan-name. REASON reason-code
Where
location-name : DALLAS9
collection-id : NULL
dbrm-name : DSNTIAUL
consistency-token: 184FA79814E1838D
reason-code : 01
plan-name : COBDBSTR
Which means The package name was not found because there is no package list for the plan.
Verify it with query
SELECT LOCATION, COLLID, NAME
FROM SYSIBM.SYSPACKLIST
WHERE PLANNAME = 'COBDBSTR';
Contact DB2 admins asking them to add the PKLIST option with the appropriate package list entry to the REBIND subcommand and rebind the application plan that is identified by name COBDBSTR
Got the correct plan from DB2ADM (DB2 administrator).
I'm trying to import csv file to SAS using proc import; I know that guessingrows argument will determine automatically the type of variable for each column for my csv file. But there is an issue with one of my CSV file which has two entire columns with blank values; those columns in my csv file should be numeric, but after running the below code, those two columns are becoming character type, is there any solutions for how to change the type of those two columns into numeric during or after importing it to SAS ?
Here below is the code that I run:
proc import datafile="filepath\datasetA.csv"
out=dataA
dbms=csv
replace;
getnames=yes;
delimiter=",";
guessingrows=100;
run;
Thank you !
Modifying #Richard's code I would do:
filename csv 'c:\tmp\abc.csv';
data _null_;
file csv;
put 'a,b,c,d';
put '1,2,,';
put '2,3,,';
put '3,4,,';
run;
proc import datafile=csv dbms=csv replace out=have;
getnames=yes;
run;
Go to the LOG window and see SAS code produced by PROC IMPORT:
data WORK.HAVE ;
%let _EFIERR_ = 0; /* set the ERROR detection macro variable */
infile CSV delimiter = ',' MISSOVER DSD lrecl=32767 firstobs=2 ;
informat a best32. ;
informat b best32. ;
informat c $1. ;
informat d $1. ;
format a best12. ;
format b best12. ;
format c $1. ;
format d $1. ;
input
a
b
c $
d $
;
if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */
run;
Run this code and see that two last columns imported as characters.
Check it:
ods select Variables;
proc contents data=have nodetails;run;
Possible to modify this code and load required columns as numeric. I would not drop and add columns in SQL because this columns could have data somewhere.
Modified import code:
data WORK.HAVE ;
%let _EFIERR_ = 0; /* set the ERROR detection macro variable */
infile CSV delimiter = ',' MISSOVER DSD lrecl=32767 firstobs=2 ;
informat a best32. ;
informat b best32. ;
informat c best32;
informat d best32;
format a best12. ;
format b best12. ;
format c best12;
format d best12;
input
a
b
c
d
;
if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */
run;
Check table description:
ods select Variables;
proc contents data=have nodetails;run;
You can change the column type of a column that has all missing value by dropping it and adding it back as the other type.
Example (SQL):
filename csv 'c:\temp\abc.csv';
data _null_;
file csv;
put 'a,b,c,d';
put '1,2,,';
put '2,3,,';
put '3,4,,';
run;
proc import datafile=csv dbms=csv replace out=have;
getnames=yes;
run;
proc sql;
alter table have
drop c, d
add c num, d num
;
I am trying to have a macro run but I'm not sure if it will resolve since I don't have connection to my database for a little while. I want to know if the macro is written correctly and will resolve the states on each pass through the code (ie do it repetitively and create a table for each state).
The second thing I would like to know is if I can run a macro through a from statement. For example let entpr be the database that I'm pulling from. Would the following resolve correctly:
proc sql;
select * from entpr.&state.; /*Do I need the . after &state?*/
The rest of my code:
libname mdt "........."
%let state = ny il ar ak mi;
proc sql;
create table mdt.&state._members
as select
corp_ent_cd
,mkt_sgmt_admnstn_cd
,fincl_arngmt_cd
,aca_ind
,prod_type
,cvyr
,cvmo
,sum(1) as mbr_cnt
from mbrship1_&state.
group by 1,2,3,4,5,6,7;
quit;
If &state contains ny il ar ak mi then as it is written, the from statement in your code will resolve to: from mbrship1_ny il ar ak mi - which is invalid SQL syntax.
My guess is that you're wanting to run the SQL statement for each of the following tables:
mbrship1_ny
mbrship1_il
mbrship1_ar
mbrship1_ak
mbrship1_mi
In which case the simplest macro would look something like this:
%macro do_sql(state=);
proc sql;
create table mdt.&state._members
as select
...
from mbrship1_&state
group by 1,2,3,4,5,6,7;
quit;
%mend;
%do_sql(state=ny);
%do_sql(state=il);
%do_sql(state=ar);
%do_sql(state=ak);
%do_sql(state=mi);
As to your question regarding whether or not to include the . the rule is that if the character following your macro variable is not a-Z, 0-9, or the underscore, then the period is optional. Those characters are the list of valid characters for a macro variable name, so as long as it's not one of those you don't need it as SAS will be able to identify where the name of the macro finishes. Some people always include it, personally I leave it out unless it's required.
When selecting data from multiple tables, whose names themselves contain some data (in your case the state) you can stack the data with:
UNION ALL in SQL
SET in Data step
As long as you are stacking data, you should also add a new column to the query selection that tracks the state.
Consider this pattern for stacking in SQL
data one;
do index = 1 to 10; do _n_ = 1 to 2; output; end; end;
run;
data two;
do index = 101 to 110; do _n_ = 1 to 2; output; end; end;
run;
proc sql;
create table want as
select
source, index
from
(select 'one' as source, * from one)
union all
(select 'two' as source, * from two)
;
The pattern can be abstracted into a template for SQL source code that will be generated by macro.
%macro my_ultimate_selector (out=, inlib=, prefix= states=);
%local index n state;
%let n = %sysfunc(countw(&states));
proc sql;
create table &out as
select
state
, corp_ent_cd
, mkt_sgmt_admnstn_cd
, fincl_arngmt_cd
, aca_ind
, prod_type
, cvyr
, cvmo
, count(*) as state_7dim_level_cnt
from
%* ----- use the UNION ALL pattern for stacking data -----;
%do index = 1 %to &n;
%let state = %scan(&states, &index);
%if &index > 1 %then %str(UNION ALL);
(select "&state" as state, * from &inlib..&prefix.&state.)
%end;
group by 1,2,3,4,5,6,7,8 %* this seems to be to much grouping ?;
;
quit;
%mend;
%my_ultimate_selector (out=work.want, inlib=mdt, prefix=mbrship1_, states=ny il ar ak mi)
If the columns of the inlib tables are not identical with regard to column order and type, use a UNION ALL CORRESPONDING to have the SQL procedure line up the columns for you.
I used following code to combine several datasets in a library with one dataset. However, according to log file, the SAS did not recognise &target..* in the macro.
The log file is shown as following:
%macro combintprice(sourcelib=,from=,going=,target=);
proc sql noprint; /*read datasets in a library*/
create table mytables as
select *
from dictionary.tables
where libname = &sourcelib
order by memname ;
select count(memname)
into:numb
from mytables;
%let numb=&numb.; /*give a number to datasets in the library*/
select memname
into :memname1-:memname&numb.
from mytables;
quit;
%do i=1 %to &numb.;
proc sql;
create table &going.&&memname&i. as
select &from.&&memname&i...*, &target..*
from &from.&&memname&i. as a left join &target. as b
on a.date=b.date;
quit;
%end;
%mend;
%combintprice(sourcelib='AXP',from=AXP.,going=WORK.,target=axp1);
It often helps to break the code down into bits when debugging this sort of thing. Let's try running this with some dummy inputs and skip the first proc sql:
%let memname1= data1;
%let memname2= data2;
%let memname3= data3;
%let numb = 3;
%macro combintprice(sourcelib=,from=,going=,target=);
%do i=1 %to &numb.;
proc sql noexec;
create table &going.&&memname&i. as
select &from.&&memname&i...*, &target..*
from &from.&&memname&i. as a left join &target. as b
on a.date=b.date;
quit;
%end;
%mend;
%combintprice(sourcelib='AXP',from=AXP.,going=WORK.,target=axp1.);
This gives the following log output:
22: LINE and COLUMN cannot be determined.
NOTE 242-205: NOSPOOL is on. Rerunning with OPTION SPOOL might allow recovery of the LINE and COLUMN where the error has occurred.
ERROR 22-322: Syntax error, expecting one of the following: a quoted string, !, !!, &, *, **, +, ',', -, /, <, <=, <>, =, >, >=, ?,
AND, AS, BETWEEN, CONTAINS, EQ, EQT, FORMAT, FROM, GE, GET, GT, GTT, IN, INFORMAT, INTO, IS, LABEL, LE, LEN, LENGTH,
LET, LIKE, LT, LTT, NE, NET, NOT, NOTIN, OR, TRANSCODE, ^, ^=, |, ||, ~, ~=.
200: LINE and COLUMN cannot be determined.
NOTE: NOSPOOL is on. Rerunning with OPTION SPOOL might allow recovery of the LINE and COLUMN where the error has occurred.
ERROR 200-322: The symbol is not recognized and will be ignored.
NOTE 137-205: Line generated by the invoked macro "COMBINTPRICE".
76 proc sql noexec; create table &going.&&memname&i. as select &from.&&memname&i...*, &target..* from &from.&&memname&i.
_
22
76 ! as a left join &target. as b on a.date=b.date; quit;
ERROR 22-322: Syntax error, expecting one of the following: a name, *.
So the problem is that your macro code is generating invalid SQL. All those error messages generated by proc sql (even with noexec set) and bits of macro variables actually get in the way here, so let's just look at what actual code generated looks like, using equivalent %put statements:
%let memname1= data1;
%let memname2= data2;
%let memname3= data3;
%let numb = 3;
%macro combintprice(sourcelib=,from=,going=,target=);
%do i=1 %to &numb.;
%put
proc sql;
%put create table &going.&&memname&i. as
select &from.&&memname&i...*, &target..*
from &from.&&memname&i. as a left join &target. as b
on a.date=b.date;
%put quit;
%end;
%mend;
%combintprice(sourcelib='AXP',from=AXP.,going=WORK.,target=axp1.);
And this is the result (with just the few semicolons omitted):
proc sql
create table WORK.data1 as select AXP.data1.*, axp1..* from AXP.data1 as a left join axp1. as b on a.date=b.date
quit
You have a few too many periods. Try fixing this so that only valid SQL is produced, and then maybe it will work as expected.
I have a table which has 120 columns and some of them is including Turkish characters (for example "ç","ğ","ı","ö"). So i want to replace this Turkish characters with English characters (for example "c","g","i","o"). When i use "TRANWRD Function" it could be really hard because i should write the function 120 times and sometimes hte column names could be change so always i have to check the code one by one because of that.
Is there a simple macro which replaces this characters in all columns .
EDIT
In retrospect, this is an overly complicated solution... The translate() function should be used, as pointed by another user. It could be integrated in a SAS function defined with PROC FCMP when used repeatedly.
A combination of regular expressions and a DO loop can achieve that.
Step 1: Build a conversion table in the following manner
Accentuated letters that resolve to the same replacement character are put on a single line, separated by the | symbol.
data conversions;
infile datalines dsd;
input orig $ repl $;
datalines;
ç,c
ğ,g
ı,l
ö|ò|ó,o
ë|è,e
;
Step 2: Store original and replacement strings in macro variables
proc sql noprint;
select orig, repl, count(*)
into :orig separated by ";",
:repl separated by ";",
:nrepl
from conversions;
quit;
Step 3: Do the actual conversion
Just to show how it works, let's deal with just one column.
data convert(drop=i re);
myString = "ç ğı òö ë, è";
do i = 1 to &nrepl;
re = prxparse("s/" || scan("&orig",i,";") || "/" || scan("&repl",i,";") || "/");
myString = prxchange(re,-1,myString);
end;
run;
Resulting myString: "c gl oo e, e"
To process all character columns, we use an array
Say your table is named mySource and you want all character variables to be processed; we'll create a vector called cols for that.
data convert(drop=i re);
set mySource;
array cols(*) _character_;
do c = 1 to dim(cols);
do i = 1 to &nrepl;
re = prxparse("s/" || scan("&orig",i,";") || "/" || scan("&repl",i,";") || "/");
cols(c) = prxchange(re,-1,cols(c));
end;
end;
run;
When changing single characters TRANSLATE is the proper function, it will be one line of code.
translated = translate(string,"cgio","çğıö");
First get all your columns from dictionary, and then replace the values of all of them in a macro do loop.
You can try a program like this (Replace MYTABLE with your table name):
proc sql;
select name , count(*) into :columns separated by ' ', :count
from dictionary.columns
where memname = 'MYTABLE';
quit;
%macro m;
data mytable;
set mytable;
%do i=1 %to &count;
%scan(&columns ,&i) = tranwrd(%scan(&columns ,&i),"ç","c");
%scan(&columns ,&i) = tranwrd(%scan(&columns ,&i),"ğ","g");
...
%end;
%mend;
%m;