2016-10-24 2 views
0

Я использовал макросвалю SAS для хранения 2 запросов sql (для них два макроса) для динамического выполнения. Разница в том, что это строка запроса для SAS SQL, а другая - строка запроса для MS SQL, которая будет выполнена с помощью сквозного объекта. Эти два запроса составлены очень точно. Я использовал% STR и% NRSTR для формирования строк запроса и сделал их сохраненными в макропеременных. Ниже целая часть написанного макро функции:Ссылка на макро переменные для динамического SQL-запроса в SAS

%LET initialDate=19Oct2016; 
%LET lastDate=19Oct2016; 
%MACRO compressDataSetFirstTime(table, library=ANY); 
PROC SQL NOPRINT; 
    /*Get the character variables*/ 
    SELECT name, varnum INTO :characterVariableList SEPARATED BY ', ' 
     FROM DICTIONARY.COLUMNS 
     WHERE libname="&library" AND memname="&table" AND type='char' 
     ORDER BY varnum; 
    /*Get the numeric variables*/ 
    SELECT name, varnum, type INTO :numericVariableList SEPARATED BY ', ' 
     FROM DICTIONARY.COLUMNS 
     WHERE libname="&library" AND memname="&table" AND type='num' 
     ORDER BY varnum; 

%PUT 文字變數清單:&characterVariableList; 
%LET characterVariableList=(&characterVariableList); 
%LET numericVariableList=%STR(&numericVariableList,); 
%PUT 數值變數清單:&numericVariableList; 
%LET queryString=%STR(SELECT); %LET macroClause=%STR(INTO); 
%LET queryMSSQL=%STR(SELECT)&numericVariableList; 
%LET listNumber=%SYSFUNC(COMPRESS(%EVAL(%SYSFUNC(COUNT(&characterVariableList, %STR(,)))+1))); 
%PUT 共有&listNumber.個文字型態變數。; 
/*Compose the query for macro and the mssql query.*/ 
%DO variableNumber=1 %TO &listNumber; 
    %IF &variableNumber LT &listNumber %THEN %DO; 
     %LET variableName=MAX(LENGTH(STRIP(%SCAN(&characterVariableList, &variableNumber)))),; 
     %LET queryString=&queryString&variableName; 
     %LET macroClause=&macroClause%STR(:variable&variableNumber,); 
     %LET variableNameMSSQL=SUBSTRING(%SCAN(&characterVariableList, &variableNumber), 1, %NRSTR(%SYSFUNC%(COMPRESS%(&)variable&variableNumber))) AS %SCAN(&characterVariableList, &variableNumber),%STR(); 
     %LET queryMSSQL=&queryMSSQL&variableNameMSSQL; 
    %END; 
    %ELSE %DO; 
     %LET variableName=MAX(LENGTH(STRIP(%SCAN(&characterVariableList, &variableNumber)))); 
     %LET queryString=&queryString&variableName; 
     %LET macroClause=&macroClause%STR(:variable&variableNumber); 
     %LET variableNameMSSQL=SUBSTRING(%SCAN(&characterVariableList, &variableNumber), 1, %NRSTR(%SYSFUNC%(COMPRESS%(&)variable&variableNumber))) AS %SCAN(&characterVariableList, &variableNumber); 
     %LET queryMSSQL=&queryMSSQL&variableNameMSSQL; 
    %END; 
%END; 
%LET queryString = &queryString&macroClause%STR(FROM &library..&table WHERE dates BETWEEN "&initialDate"D AND "&lastDate"D;); 
%LET queryMSSQL = &queryMSSQL%STR(FROM dbo.&table WHERE dates BETWEEN %NRSTR("%SYSFUNC(PUTN("&initialDate"D, YYMMDD10.))") AND %NRSTR("%SYSFUNC(PUTN("&lastDate"D, YYMMDD10.))");); 
%PUT The query string with macro clause:&queryString; 
/*Execute the query for macro*/ 
    &queryString 
/* 
    This is for examination. 
%DO checkNumber=1 %TO &listNumber; 
    %PUT variable&checkNumber.接受到的長度:%SYSFUNC(TRIM(&&variable&checkNumber)); 
%END;*/ 
%PUT 遞過功能MSSQL查詢語句:&queryMSSQL; 
/*Execute the mssql query with the pass-through facility*/ 
    CONNECT TO SQLSVR AS sjconn 
     (DATABASE="***" USER=*** PASSWORD=***); 
     CREATE TABLE Desirable_Result AS 
     SELECT * 
     FROM connection to sjconn 
     ( 
      /* The printed result of queryMSSQL from log using %PUT. */ 
      /* &queryMSSQL */ 
     ); 
     DISCONNECT FROM sjconn; 
QUIT; 
%MEND; 

проблема, которую я встретил это запрос сохраняется в макропеременной не может быть выполнен в PROC SQL с проходным объектом.

Второй запрос состоит из функции SUBSTRING в MSSQL,% SYSFUNC и некоторые макропеременные, которая появляется как следующий, с% PUT:

 
SELECT SUBSTRING(var, 1, %SYSFUNC(COMPRESS(&len_var))) AS var 
FROM table 
WHERE date BETWEEN "%SYSFUNC(PUTN("&firstdate"D, YYMMDD10.))" AND 
"%SYSFUNC(PUTN("&lastdate"D, YYMMDD10.))";

Предположит & запроса хранит строку запроса, мои проблема в том, что если я использовал напечатанный результат в журнале и поместил его в PROC SQL с помощью сквозного средства, он работал, но если я использовал запрос & и поместил его в PROC SQL с помощью сквозного средства, он не удался.

В двух словах,

Это работает

CONNECT TO SQLSVR AS conn (related setting); 
CREATE TABLE TMP AS 
SELECT * 
FROM connection to conn 
(
    /* The following query is the result I coped from the log where I used %PUT to print <br> the content of &query */ 
   SELECT SUBSTRING(var, 1, %SYSFUNC(COMPRESS(&len_var))) AS var 
   FROM table 
   WHERE date BETWEEN "%SYSFUNC(PUTN("&firstdate"D, YYMMDD10.))" AND    "%SYSFUNC(PUTN("&lastdate"D, YYMMDD10.))"; 
); 

Это не удается

CONNECT TO SQLSVR AS conn (*related setting*); 
CREATE TABLE TMP AS 
SELECT * 
FROM connection to conn 
(
    &query 
); 

Сообщение об ошибке в лог-дисплеях, что синтаксис около 'SYSFUNC' неверна.

Любая подсказка, почему это так?

+0

Возможно, я совсем не здесь, но ваш SYSFUNC не имеет знака процента, как у вас в одном месте. Im ссылаясь на переменные даты в предложении where. похоже, что это должна быть функция put или аналогичная. это даже необходимо, так как вы создаете константы даты & firstdate и & lastdate. Но вы говорите, что это работает в случае 1. – Jonas

+0

@ Джонас, это недостающая часть, потому что моя неосторожная публикация. Я проверил содержимое (моего вопроса) еще раз. Спасибо за ваше упоминание. –

ответ

3

Вы не можете использовать %SYSFUNC таким образом, к сожалению. %SYSFUNC (которому требуется %, если вы его не оставили, только из-за опечатки) должен выполнить системную функцию; вы не просите об этом здесь. Ваше «это работает» на самом деле не работает или, по крайней мере, не должно, и, вероятно, не делает того, что вы ожидаете от него, если оно действительно что-то возвращает (что меня очень удивило бы).

Например, это простейшее-оф-вещи:

%let x = %SYSFUNC("&firstdate"D, YYMMDD10.); 

завершается с ошибкой:

ERROR: Function name missing in %SYSFUNC or %QSYSFUNC macro function reference. 

Итак, как же мы получаем, что вокруг? Довольно легко, используйте простую функцию putn. Фактически вы можете просто обернуть его вокруг того, что у вас есть сейчас, и оно будет работать напрямую.

%let firstdate=01JAN2015; 
%let x = %SYSFUNC(putn("&firstdate"D, YYMMDD10.)); 
%put &=x; 

Относительно того, почему это, кажется, работает для вас, если вы запустите его в первый путь, а не второй ... кто знает. Если это на самом деле работает первым способом (если вы неточно перекодировали пример), то мое предложение состояло бы в том, что вы сделали что-то с макросом, цитирующим, что компилятор SQL не желает его делать.%unquote, когда вы используете, это не плохая идея, как первый шаг к ее выяснению, или переключитесь на то, как вы его цитируете (используйте %str вместо %nrstr или используйте %bquote вместо %str и т. Д.), Чтобы увидеть, что работает, а что нет ; PROC SQL является, как известно, тонким, когда дело доходит до макрокоманды, а также то, что шаг данных будет с успехом автоматически отменять SQL, не всегда.

+0

Джо, спасибо за ваше указание о PUTN, оцените ваш добрый ответ на мою ужасную публикацию. Из-за окружающей среды SAS, с которой я работаю, я не могу напрямую копировать код на этот сайт (без Интернета моего рабочего стола), поэтому я должен набрать простой пример, аналогичный части в моей исходной программе SAS. Я снова отредактировал вопрос. В настоящее время у меня есть решение, но оно не может достичь моей желаемой цели. Я буду рассматривать ваше предложение и проверять их по одному. Еще раз спасибо, Джо. –

+0

Скотт - вы хотите создать тестовый пример, который можно запустить. Используйте одну из встроенных таблиц на SQL-сервере, что мы будем использовать и в наших версиях сервера sql. Вы спрашиваете о проблеме, которая, по-видимому, связана с деталями кода, который вы не показываете, поэтому на самом деле невозможно помочь в противном случае. – Joe