簡體   English   中英

SAS 傳遞查詢使用硬編碼日期運行,但不使用宏變量作為日期

[英]SAS Passthrough Query Runs With Hard Coded Dates, but not Macro Variables as Dates

我有一個運行 SAS 通道查詢的腳本,該查詢連接到 Oracle 數據庫。 這是在 Unix 服務器上運行的 cronjob 的一部分,多年來一直沒有問題。 然而,在過去的幾周里,這項工作已經開始在這一特定步驟上掛起——根據日志,它過去需要大約 15 秒才能運行,但現在將無限期地運行,直到我們不得不終止該工作。 日志中沒有相關的錯誤或警告 - 該作業將創建一個鎖定文件並無限期運行,直到我們必須終止它。

作業掛起的步驟粘貼在下面。 有兩個宏變量 &start_dt 和 &end_dt,代表作業拉取銷售數據的日期范圍。

在調查過程中,我們嘗試了幾種不同的方法,並且能夠通過改變三件事來讓這一步成功運行,並且在通常的時間內運行:

  • 通過連接到同一服務器的企業指南客戶端運行腳本,而不是通過 CLI / shell 腳本運行腳本

  • 將步驟寫入的庫更改為工作而不是寫入
    數據集到 salesdata 庫(如下面的代碼所示)

  • 將日期更改為硬編碼值而不是宏變量。

至於日期變量本身,它們是date9 格式的字符串,例如&start_dt = '08-May-22', &end_dt = '14-May-22'。 最初我懷疑這個問題與日期的結構方式有關,因為這是我繼承的一個較舊的項目,但我很困惑為什么直到幾周前,即使這些格式奇怪的日期,這項工作也能毫無問題地運行這么久宏變量。

我考慮的另一種可能性是 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 中,在常量周圍使用單引號很重要,因為它將雙引號中的字符串解釋為 object 名稱。

因此,如果您在 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM