2017-03-05 18 views
1

단일 값 입력 매개 변수를 사용하고 다른 계산에서 입력 매개 변수에 대한 문자열을 생성하는 스크립트 계산보기에 일부 SQL 스크립트가 있다고 가정 해 보겠습니다. 전망.HANA - SQL 스크립트에서 WHERE IN() 절에 문자열 변수 전달

BEGIN 
declare paramStr clob; 
params = select foo 
     from bar 
     where bar.id = :IP_ID; 

select '''' || string_agg(foo, ''', ''') || '''' 
into paramStr 
from :params; 

var_out = select * 
      from "_SYS_BIC"."somepackage/MULTIPLE_IP_VIEW"(PLACEHOLDER."$$IP_IDS$$" => :paramStr); 
END 

예상대로 작동합니다. 나는 var_out 쿼리를 변경하고 where 절

BEGIN 
... 

var_out = select * 
      from "_SYS_BIC"."somepackage/MULTIPLE_IP_VIEW" 
      where "IP_IDS" in(:paramStr); 
END 

뷰 활성화에 변수를 사용하려고하지만, 그러나 나는 쿼리로부터 결과를 얻을 수 없습니다. 런타임 오류가 없으며 빈 결과 집합입니다. 수동으로 값을 WHERE IN() 절로 전달하면 모든 것이 올바르게 작동합니다. 초보적인 문제인 것처럼 보이지만 작동시키지 못합니다. 난

+0

이 경우 어떤 오류 메시지가 나옵니까? 또한 : 귀하의보기 이름에서 빠진 큰 따옴표가 있습니다. 그리고 여기서 뭘하려고합니까? 입력 매개 변수 나 변수에 값을 입력하면 교환 할 수 없습니다. –

+0

죄송합니다. 오타가 수정되었습니다. 어떤 활성화 또는 런타임 오류도 발생하지 않습니다. 스크립트 된 calc보기를 쿼리 할 때 결과가 다시 나타나지 않지만'WHERE "SOME_COLUMN"IN '('ip1 ','ip2 ')'잘 작동합니다. 그리고 내가 말했듯이, 첫 번째 예제와 같은 IP로이 구현을 사용하면 효과가 있습니다. – Jenova

+0

이 질문과 관련이 없지만 HANA 최적화 프로그램이 필터를 올바르게 적용하지 않는 복잡한 서비스가 있습니다. 예를 들어 하나의 대출 번호에 대한 잔액을 계산하는 서비스가있는 경우 HANA 최적화 도구는 훌륭하게 작동하지만 입력을 변형하여 특정 계정 번호에 대한 여러 대출 번호를 전달할 방법이 없습니다. 이 변환을 그래픽 방식으로 결합하면 큰 성능 손실 없이는 작동하지 않습니다. 대신 필자는 스크립트 계산 창에서 그래픽보기를 래핑하여 입력을 변환하고 성능 저하없이 여러 매개 변수로 원본보기를 쿼리합니다. – Jenova

답변

0

좋아, 그래서 당신이 동적 문을 만들 수 있습니다. 을 IN 조건을 위해 노력하고 여기서 뭐, 당신이 희망하는 것 char(39)보다는 내 연결 발현 '''',하지만 바나나 :(사용하여 시도했다 당신이 paramStr을 채운 일단은 매개 변수의 집합으로 처리 할 것

전혀 그렇지 않다 그
이의이 코멘트에서 귀하의 예제와 함께 가자 :.. paramStr가 작성됩니다 어떻게됩니까 paramStr = ' 'ip1','ip2' '

, 귀하의 코드에 :

var_out = select * 
      from "_SYS_BIC"."somepackage/MULTIPLE_IP_VIEW" 
      where "IP_IDS" in(' ''ip1'',''ip2'' '); 

그래서, 대신 IP_DS = 'ip1' or IP_DS = 'ip2' 일치하는 기록을 찾고 당신은 말 그대로 IP_DS = ' 'ip1','ip2' ' 일치하는 레코드를 찾고 있습니다.

이 문제를 해결하는 한 가지 방법은 APPLY_FILTER() 기능을 사용하는 것입니다.

var_out = select * 
      from "_SYS_BIC"."somepackage/MULTIPLE_IP_VIEW"; 

filterStr = ' "IP_IDS" in (''ip1'',''ip2'') '; 

var_out_filt = APPLY_FILTER(:var_out, :filterStr) ; 

얼마전에 내가 작성한 글 : "On multiple mistakes with IN conditions". 또한 APPLY_FILTER에 대한 설명서를 살펴보십시오.

+0

그게 효과가 있었지만 지금은 첫 번째 실행에서 끔찍한 성능을 얻고 있습니다. 그리고 수동으로 동일한 쿼리를 실행하면 번개가 빨리납니다 ... – Jenova

0

"2315085 - 잘못된 구문 오류로 인해 스크립트 된 계산보기에서 다중 값 매개 변수가있는 쿼리"가 실제로 처음 시도했을 때 실패한 APPLY_FILTER() 접근 방식을 보여줍니다.

또한 입력 매개 변수의 항목 배열을 사용하여 긴 varchar 문자열을 사용 가능한 목록 내 조건 자로 변환하는 UDF_IN_LIST 함수를 제공합니다.

다음 (범위 3) 문자열이 너무 긴 예외 - : 그것은 sps11에서 작동 할 수없는 불행하게도

는 가능한 몇 가지 매개 변수 (문자열 길이 오버 플로우에 대한 경고로 오류를 변환하는 SAP 참고 2457876)에도 불구하고 111.03 레브 ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini', 'System') set ('sqlscript', 'typecheck_procedure_input_param') = '거짓', RECONFIGURE; 에서 다음

선택 캘크보기

* -recompile

: var_tempout 곳 OBJECT_ID ('BWOBJDES "에서 I_LIST을 선택합니다."CROSS_AREA :: UDF_INLIST_P"(: in_objectids, ','));

올바르지 않은 숫자 예외 -이 잘못되었습니다 수

그러나이 기능이 작동하게 밖으로 스크립트를 복용 ...

11 레벨 APPLY_FILTER이 유일한 해결 될 것으로 보인다 SPS. 그리고 SPS 12의 레브가 무엇이 될지 말하기 란 정말로 어렵습니다.

FUNCTION "BWOBJDES"."CROSS_AREA::UDF_INLIST_P"(str_input nvarchar(5000), 
delimiter nvarchar(10)) 
RETURNS table (I_LIST INTEGER) LANGUAGE SQLSCRIPT SQL SECURITY INVOKER AS 
/********* Begin Function Script ************/ 
BEGIN 
DECLARE cnt int; 
DECLARE temp_input nvarchar(128); 
DECLARE slice NVARCHAR(10) ARRAY; 

temp_input := :str_input; 
cnt := 1; 
WHILE length(temp_input) > 0 DO 
    if instr(temp_input, delimiter) > 0 then 
     slice[:cnt] := substr_before(temp_input,delimiter); 
     temp_input := substr_after(temp_input,delimiter); 
     cnt := :cnt + 1; 
    else 
     slice[:cnt] := temp_input; 
     break; 
    end if; 
END WHILE; 
tab2 = UNNEST(:slice) AS (I_LIST); 
return select I_LIST from :tab2; 
END; 

CREATE PROCEDURE "MY_SCRIPTED_CV/proc"(IN numbers NVARCHAR(5000), OUT 
var_out 
MY_TABLE_TYPE) language sqlscript sql security definer reads sql data with 
result view 
"MY_SCRIPTED_CV" as 
/********* Begin Procedure Script ************/ 
BEGIN 
    -- not working 
    --var_out = select * from MY_TABLE where NUMBER in (select I_LIST from 
    --UDF_INLIST_P(:numbers,',')); 

    -- working 
    DECLARE cnt int; 
    DECLARE temp_input nvarchar(128); 
    DECLARE slice NVARCHAR(13) ARRAY; 
    DECLARE delimiter VARCHAR := ','; 

    temp_input := replace(:numbers, char(39), ''); 
    cnt := 1; 
    WHILE length(temp_input) > 0 DO 
    if instr(temp_input, delimiter) > 0 then 
     slice[:cnt] := substr_before(temp_input,delimiter); 
     temp_input := substr_after(temp_input,delimiter); 
     cnt := :cnt + 1; 
    else 
     slice[:cnt] := temp_input; 
     break; 
    end if; 
    END WHILE; 
l_numbers = UNNEST(:slice) AS (NUMBER); 

var_out= 
SELECT * 
FROM MAIN AS MA 
INNER JOIN l_numbers as LN 
ON MAIN.NUMBER = LN.NUMBER 

END;