2016-09-06 5 views
0

DashDB에서 Node-RED를 사용하여 IBM Bluemix 솔루션을 개발 중입니다. WHERE IN SQL 절에 ACCOUNT_ID이라는 열에 여러 값을 구문 분석 할 때 문제가 발생했습니다. 난 그냥 하나 개의 매개 변수를 전달하는 경우는 완벽하게 작동하지만이 두 개 이상있을 때 그것은 folliwng 오류 메시지와 함께 실패합니다 Bluemix DashDB WHERE IN 문이 작동하지 않습니다.

msg.account = msg.req.query.account; 
msg.datestart = msg.req.query.datestart; 
msg.dateend = msg.req.query.dateend; 
var strPayload = "SELECT A.*, B.DESCRIPTION AS ACCOUNT_NAME, C.DESCRIPTION AS TYPE_NAME "; 
strPayload += " FROM NORMALIZED_TABLE A "; 
strPayload += " INNER JOIN ACCOUNT B ON A.ACCOUNT_ID = B.ACCOUNT_ID "; 
strPayload += " INNER JOIN NORMALIZED_TYPE C ON A.TYPE_ID = C.TYPE_ID"; 
strPayload += " WHERE A.ACCOUNT_ID IN(?) AND DATE_START>=? AND DATE_END<=?"; 
strPayload += " FETCH FIRST 1000 ROWS ONLY"; 
msg.payload = strPayload; 
return msg; 

은 기본적으로 내 문제는 여기에 있습니다 : WHERE A.ACCOUNT_ID IN(?). 하나의 값으로, 웹 서비스가 호출되고 그것을 잘 다음과 같이 작동합니다

/getPreviewReport?datestart=2016-08-01&dateend=2016-08-01&account=44 

을하지만 아래와 같은 계정 매개 변수에 여러 값을 통과 할 때, 그것은 실패

/getPreviewReport?datestart=2016-08-01&dateend=2016-08-01&account=44,45,2 

노드 빨간색 오류 :

dashDB query node: Error: [IBM][CLI Driver][DB2/LINUXX8664] SQL0420N Invalid character found in a character string argument of the function "DECIMAL". SQLSTATE=22018

이 문제를 어떻게 다시 해결할 수 있습니까?

+0

이 더 구체적으로 하나를 Bluemix보다 SQL 질문입니다. 더 많은 사람들이 볼 수 있도록 SQL 태그를 추가했습니다. – ralphearle

+0

나는 Ralpherle에 동의하지 않는다. 일단 SQL 명령 행에서 똑같은 명령을 실행하면 완벽하게 작동하지만 dashdb와 node-red에서는 동일하지 않다. –

+0

태그를 다시 붙이면 좋은 질문을 가능한 한 많이 얻을 수 있습니다. SQL에 대한 고급 지식을 가진 사람이 문제를 해결할 수 있습니다. DashDB 태그를 추가해도이 서비스에만 해당하는 것은 확실하지 않습니다. – ralphearle

답변

0

내가 아는 모든 SQL 데이터베이스는 구문 분석없이 바인드 변수 값으로 제공된 값을 단일 값으로 처리합니다.

가변 길이 IN 목록을 처리하는 일반적인 방법은 동적 SQL을 사용하는 것입니다. 불행히도 SQL 인젝션 공격이 자주 발생합니다. 특히 비 SMTP화된 요청 속성을 쿼리에 직접 전달하는 경우가 그렇습니다.

당신과 같이 매개 변수 문자열을 구문 분석하는 재귀 SQL을 사용하여 안전의 비트를 추가 할 수 있습니다

-- parse comma-separated values into a "table" 
WITH lst (lvl, id, tail) AS ( 
    SELECT 1, CASE WHEN LOCATE(',',input) > 0 
       THEN TRIM(LEFT(input, LOCATE(',',input)-1)) 
       ELSE TRIM(input) 
     END,  
     CASE WHEN LOCATE(',',input) > 0 
       THEN SUBSTR(input, LOCATE(',',input)+1)  
       ELSE '' 
     END 
    FROM table (values ?) as (input) 
    UNION ALL 
    SELECT lvl + 1, CASE WHEN LOCATE(',', tail) > 0 
       THEN TRIM(LEFT(tail, LOCATE(',', tail)-1))  
       ELSE TRIM(tail) 
     END,  
     CASE WHEN LOCATE(',', tail) > 0 
       THEN SUBSTR(tail, LOCATE(',', tail)+1)  
       ELSE '' 
     END 
    FROM lst 
    WHERE lvl < 100 AND tail != '') 

SELECT a.*, b.description as account_name, c.description as type_name 
FROM normalized_table a 
INNER JOIN account b ON a.account_id = b.account_id 
INNER JOIN normalized_type c ON a.type_id = c.type_d 
-- join to the parameter "table" on id 
INNER JOIN lst ON a.account_id = lst.id 
WHERE date_start>=? AND date_nd<=? 
FETCH FIRST 1000 ROWS ONLY