Запрос SAS Passthrough выполняется с жестко закодированными датами, но не с макропеременными в качестве дат

У меня есть сценарий, который запускает сквозной запрос SAS, который подключается к базе данных Oracle. Это было частью cronjob, работающего на Unix-сервере, и не было проблем в течение многих лет. Однако в последние несколько недель задание начало зависать на этом конкретном шаге — согласно журналам, раньше оно выполнялось около 15 секунд, но теперь оно будет выполняться бесконечно, прежде чем нам придется убить задание. В журнале нет связанных ошибок или предупреждений — задание создаст файл блокировки и просто будет работать бесконечно, пока нам не придется его убить.

Шаг, на котором задание зависает, вставлен ниже. Есть две макропеременные &start_dt и &end_dt, которые представляют диапазон дат, для которого задание извлекает данные о продажах.

В ходе исследования мы попробовали несколько разных подходов, и смогли заставить этот шаг работать успешно и в обычное время, изменив три вещи:

  • запуск сценария через клиент Enterprise Guide, который подключается на тот же сервер, в отличие от запуска скрипта через CLI/shell сценарий

  • Изменение библиотеки, в которую шаг пишет, чтобы она работала, а не записывалась
    набор данных в библиотеку данных продаж (как показано в коде ниже)

  • Изменение дат на жестко заданные значения вместо макропеременных.

Что касается самих переменных даты, они представляют собой строки в формате date9, например &start_dt = '08-мая-22', &end_dt = '14-мая-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

Похоже, вы просто спрашиваете об этом условии (between &start_dt and &end_dt), которое, как вы утверждаете, не работает. Но я не вижу нигде в вашем посте, где вы показываете выражение, которое действительно работает.

Tom 18.05.2022 00:28

@Tom, если я изменю &start_dt и &end_dt на жестко закодированные значения «08-May-22» и «14-May-22» и запишу результаты для работы, а не на диск, шаг выполняется без проблем.

ply 18.05.2022 00:38

И как вы пытаетесь присвоить значения макропеременным? Кроме того, Oracle действительно не хочет знать, о каком веке вы говорите? Это 1922, 1822?

Tom 18.05.2022 00:41

@Tom Я добавил более подробную информацию в ответ ниже, макропеременные назначаются с использованием шага данных для объединения некоторых строк и применения форматов из набора данных календаря дат. Изменение формата на этом этапе для использования 4-х символьных лет вместо двух, по-видимому, решает проблему. Спасибо, что указали мне правильное направление, я продолжу и приму ваш ответ.

ply 18.05.2022 01:18

Вопрос stackoverflow.com/questions/60452323/… относится к той же теме

Richard 18.05.2022 04:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
5
16
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Какой стиль вам нужно использовать для констант даты в 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';

Похоже, что несколько недель назад наши администраторы баз данных обновили некоторые настройки в Oracle, которые повлияли на то, насколько строга база данных с точки зрения того, какие форматы она может принимать. Итак, версии, которые мы использовали ранее (ДД-МММ-ГГ), теперь неприемлемы.

ply 18.05.2022 00:58

Или вы просто перешли от таких строк, как 28-APR-22, которые, возможно, легче распознать в порядке ДЕНЬ-МЕСЯЦ-ГОД, к более неоднозначной строке, такой как 17-MAY-22, которая может означать сегодня, но также может означать почти 5 лет? тому назад?

Tom 18.05.2022 05:19

Так что ответ @Tom был полезен - похоже, что наши администраторы баз данных несколько недель назад обновили некоторые настройки, которые повлияли на то, насколько строг 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-guide. Пример ниже:

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;

Почему бы просто не использовать формат DATE11 для генерации строки DD-MMM-YYYY?

Tom 18.05.2022 05:04

Другие вопросы по теме

Похожие вопросы