SAS 直通查询使用硬编码日期运行,但不使用宏变量作为日期
SAS Passthrough Query Runs With Hard Coded Dates, but not Macro Variables as Dates
我有一个脚本 运行 是一个连接到 Oracle 数据库的 SAS passthrough 查询。这是 运行 在 Unix 服务器上的 cronjob 的一部分,多年来一直没有问题。然而,在过去的几周里,这项工作已经开始在这一特定步骤上挂起 - 根据日志,它过去需要大约 15 秒才能 运行 但现在只会 运行 无限期地结束之前工作。日志中没有相关的错误或警告 - 该作业将创建一个锁定文件,并且 运行 无限期地创建,直到我们必须终止它。
作业挂掉的步骤贴在下面。有两个宏变量 &start_dt 和 &end_dt,它们表示 运行ge 作业提取销售数据的日期。
在调查过程中,我们尝试了几种不同的方法,通过改变三件事,能够在通常的时间内成功地完成这一步 运行:
运行通过企业指南客户端连接脚本
到同一台服务器,而不是通过 CLI / shell 运行ning 脚本
脚本
将步骤写入的库改为工作而不是写入
数据集到 salesdata 库(如下面的代码所示)
将日期更改为硬编码值而不是宏变量。
至于日期变量本身,它们是date9格式的字符串,例如
&start_dt = '22 年 5 月 8 日',&end_dt = '22 年 5 月 14 日'。最初我怀疑这个问题与日期的结构方式有关,因为这是我继承的一个较旧的项目,但我很困惑为什么这份工作 运行 这么长时间都没有问题,直到几周前,即使这些格式奇怪的日期宏变量。
我考虑的另一种可能性是,当执行到这一步时,unix 服务器上的某种资源被锁定,可能是由于某种挂起的作业或与旧文件(如日志)的其他一些冲突或以前的 sas 数据集。
下面粘贴的脚本中步骤的问题版本:
PROC SQL;
connect to oracle(user=&uid pass=&pwd path='@dw');
create table salesdata.shipped as
Select
SKN_NBR,
COLOR_NBR,
SIZE_NBR,
SALESDIV_KEY,
ORDER_LINE_QTY as QUANTITY label="SUM(ORDER_LINE_QTY)",
EX1 as DOLLARS label="SUM(EX1)" from connection to oracle(
select
A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC'),
SUM(A1."ORDER_LINE_QTY"),
SUM(A1."ORDER_LINE_QTY" * A1."ORDER_LINE_PRICE_AMT")
from DW.ORDERLINE A1, DISTINCT_SKN A2, DW.ORDERSTATUSTYPE A3
where
A2."SKN_NBR" = A1."SKN_NBR" AND
A1."CURRENT_STATUS_DATE" Between &start_dt and &end_dt AND
A1."ORDERLINESTATUS_KEY" = A3."ORDERLINESTATUS_KEY" AND
A3."ORDERSTATUS_SHIPPED" = 'Y' AND
A1."ORDER_LINE_PRICE_AMT" > 0
group by A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC')
order by A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC')
) as t1(SKN_NBR, COLOR_NBR, SIZE_NBR, SALESDIV_KEY, ORDER_LINE_QTY, EX1)
;
disconnect from oracle; quit;
[1]: https://i.stack.imgur.com/GGjin.jpg
您需要为 Oracle 中的日期常量使用什么样式取决于您在 Oracle 中的设置。但通常你可以使用像下面这样的表达式
date '2022-05-14'
'2022-05-14'
您似乎声称在您的系统上您可以使用像
这样的值
'14-May-22'
(Oracle 怎么知道你指的是哪个世纪?)。
请注意,在 Oracle 中,在常量周围使用单引号很重要,因为它将双引号中的字符串解释为对象名称。
因此,如果您在 SAS 中有日期值,只需确保使宏变量值看起来像 Oracle 想要的那样。
例如,要将 ENDDT 设置为今天的日期,您可以使用:
data _null_;
call symputx('enddt',quote(put(today(),date11.),"'"));
run;
这与
相同
%let enddt='17-MAY-2022';
所以@Tom 的回答很有帮助——我们的 DBA 似乎在几周前更新了一些设置,这影响了 Oracle 在接受哪些日期格式方面的严格程度。
就其价值而言,日期宏变量是使用读取日期键数据集的笨重数据步骤动态构建的:
您会注意到为 bost 变量放在一起的日期字符串的最后一段使用 year2。格式,所以只有年份的最后两位数字。
就@Tom 的观点而言,这显然让 Oracle 混淆了它属于哪个世纪,因此工作被挂断了。
data dateparm;
set salesdata.week_end_date;
start = "'" || put(day(week_end_date - 6), z2.) || '-' || put(week_end_date - 6, monname3.) || '-' ||
put(week_end_date - 6, year2.) || "'";
end = "'" || put(day(week_end_date), z2.) || '-' || put(week_end_date, monname3.) || '-' ||
put(week_end_date, year2.) || "'";
call symput('start_dt', start);
call symput('end_dt', end);
run;
一旦我将此步骤更改为使用 year4。最后一块的格式,这项工作能够 运行 在 unix 和 E 指南上顺利进行。示例如下:
data dateparm;
set npdd.week_end_date;
start = "'" || put(day(week_end_date - 6), z2.) || '-' || put(week_end_date - 6, monname3.) || '-' ||
put(week_end_date - 6, year4.) || "'";
end = "'" || put(day(week_end_date), z2.) || '-' || put(week_end_date, monname3.) || '-' ||
put(week_end_date, year4.) || "'";
call symput('start_dt', start);
call symput('end_dt', end);
run;
我有一个脚本 运行 是一个连接到 Oracle 数据库的 SAS passthrough 查询。这是 运行 在 Unix 服务器上的 cronjob 的一部分,多年来一直没有问题。然而,在过去的几周里,这项工作已经开始在这一特定步骤上挂起 - 根据日志,它过去需要大约 15 秒才能 运行 但现在只会 运行 无限期地结束之前工作。日志中没有相关的错误或警告 - 该作业将创建一个锁定文件,并且 运行 无限期地创建,直到我们必须终止它。
作业挂掉的步骤贴在下面。有两个宏变量 &start_dt 和 &end_dt,它们表示 运行ge 作业提取销售数据的日期。
在调查过程中,我们尝试了几种不同的方法,通过改变三件事,能够在通常的时间内成功地完成这一步 运行:
运行通过企业指南客户端连接脚本 到同一台服务器,而不是通过 CLI / shell 运行ning 脚本 脚本
将步骤写入的库改为工作而不是写入
数据集到 salesdata 库(如下面的代码所示)将日期更改为硬编码值而不是宏变量。
至于日期变量本身,它们是date9格式的字符串,例如 &start_dt = '22 年 5 月 8 日',&end_dt = '22 年 5 月 14 日'。最初我怀疑这个问题与日期的结构方式有关,因为这是我继承的一个较旧的项目,但我很困惑为什么这份工作 运行 这么长时间都没有问题,直到几周前,即使这些格式奇怪的日期宏变量。
我考虑的另一种可能性是,当执行到这一步时,unix 服务器上的某种资源被锁定,可能是由于某种挂起的作业或与旧文件(如日志)的其他一些冲突或以前的 sas 数据集。
下面粘贴的脚本中步骤的问题版本:
PROC SQL;
connect to oracle(user=&uid pass=&pwd path='@dw');
create table salesdata.shipped as
Select
SKN_NBR,
COLOR_NBR,
SIZE_NBR,
SALESDIV_KEY,
ORDER_LINE_QTY as QUANTITY label="SUM(ORDER_LINE_QTY)",
EX1 as DOLLARS label="SUM(EX1)" from connection to oracle(
select
A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC'),
SUM(A1."ORDER_LINE_QTY"),
SUM(A1."ORDER_LINE_QTY" * A1."ORDER_LINE_PRICE_AMT")
from DW.ORDERLINE A1, DISTINCT_SKN A2, DW.ORDERSTATUSTYPE A3
where
A2."SKN_NBR" = A1."SKN_NBR" AND
A1."CURRENT_STATUS_DATE" Between &start_dt and &end_dt AND
A1."ORDERLINESTATUS_KEY" = A3."ORDERLINESTATUS_KEY" AND
A3."ORDERSTATUS_SHIPPED" = 'Y' AND
A1."ORDER_LINE_PRICE_AMT" > 0
group by A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC')
order by A1."SKN_NBR",
A1."COLOR_NBR",
A1."SIZE_NBR",
decode(A1."SALESDIV_KEY", 'ILB', 'IQ',
'IQ ', 'IQ',
'IQC', 'IQ',
'ISQ', 'IQ',
'IWC', 'IQ',
'QVC')
) as t1(SKN_NBR, COLOR_NBR, SIZE_NBR, SALESDIV_KEY, ORDER_LINE_QTY, EX1)
;
disconnect from oracle; quit;
[1]: https://i.stack.imgur.com/GGjin.jpg
您需要为 Oracle 中的日期常量使用什么样式取决于您在 Oracle 中的设置。但通常你可以使用像下面这样的表达式
date '2022-05-14'
'2022-05-14'
您似乎声称在您的系统上您可以使用像
这样的值'14-May-22'
(Oracle 怎么知道你指的是哪个世纪?)。
请注意,在 Oracle 中,在常量周围使用单引号很重要,因为它将双引号中的字符串解释为对象名称。
因此,如果您在 SAS 中有日期值,只需确保使宏变量值看起来像 Oracle 想要的那样。
例如,要将 ENDDT 设置为今天的日期,您可以使用:
data _null_;
call symputx('enddt',quote(put(today(),date11.),"'"));
run;
这与
相同%let enddt='17-MAY-2022';
所以@Tom 的回答很有帮助——我们的 DBA 似乎在几周前更新了一些设置,这影响了 Oracle 在接受哪些日期格式方面的严格程度。
就其价值而言,日期宏变量是使用读取日期键数据集的笨重数据步骤动态构建的:
您会注意到为 bost 变量放在一起的日期字符串的最后一段使用 year2。格式,所以只有年份的最后两位数字。
就@Tom 的观点而言,这显然让 Oracle 混淆了它属于哪个世纪,因此工作被挂断了。
data dateparm;
set salesdata.week_end_date;
start = "'" || put(day(week_end_date - 6), z2.) || '-' || put(week_end_date - 6, monname3.) || '-' ||
put(week_end_date - 6, year2.) || "'";
end = "'" || put(day(week_end_date), z2.) || '-' || put(week_end_date, monname3.) || '-' ||
put(week_end_date, year2.) || "'";
call symput('start_dt', start);
call symput('end_dt', end);
run;
一旦我将此步骤更改为使用 year4。最后一块的格式,这项工作能够 运行 在 unix 和 E 指南上顺利进行。示例如下:
data dateparm;
set npdd.week_end_date;
start = "'" || put(day(week_end_date - 6), z2.) || '-' || put(week_end_date - 6, monname3.) || '-' ||
put(week_end_date - 6, year4.) || "'";
end = "'" || put(day(week_end_date), z2.) || '-' || put(week_end_date, monname3.) || '-' ||
put(week_end_date, year4.) || "'";
call symput('start_dt', start);
call symput('end_dt', end);
run;