2014-08-27 6 views
3

저는 FireDAC를 통해 인터페이스하는 IB 데이터베이스를 실행 중입니다.SQL 변환 오류/select 문에 매개 변수를 삽입하는 방법?

다음 동적 쿼리가 작동합니다

INSERT INTO RELATIONS (C_ID, M_ID, A_ID) 
SELECT c.C_ID, 0, a.A_ID 
FROM CATEGORIES c, ACTIONS a 
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION 

나는 관계에 열 A_INDEX (정수)를 추가합니다. 이 칼럼에서는 매개 변수를 제공하므로 다음과 같이 처리합니다.

INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX) 
SELECT c.C_ID, 0, a.A_ID, :A_INDEX 
FROM CATEGORIES c, ACTIONS a 
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION 

그러나 이것은 작동하지 않습니다. 어떤 이유로 쿼리를 실행할 때 CATEGORY param에 대한 변환 오류가 있다고 불평합니다.

이이 쿼리 작업의 전체 코드입니다 :

procedure Test; 
    var 
    Query: TFDQuery; 
    begin 
    Query := TFDQuery.Create(nil); 
    try 
     Query.Connection := DBDataModule.dbMain; 
     Query.ResourceOptions.ParamCreate := False; 

     Query.SQL.BeginUpdate; 

     Query.SQL.Add('INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)'); 
     Query.SQL.Add('SELECT c.C_ID, 0, a.A_ID,:A_INDEX'); 
     Query.SQL.Add('FROM CATEGORIES c, ACTIONS a'); 
     Query.SQL.Add('WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION'); 

     Query.SQL.EndUpdate; 

     Query.Params.CreateParam(TFieldType.ftInteger, 'A_INDEX', ptInput); 
     Query.Params.CreateParam(TFieldType.ftFixedWideChar, 'CATEGORY', ptInput); 
     Query.Params.CreateParam(TFieldType.ftFixedWideChar, 'ACTION', ptInput); 
     Query.ParamByName('CATEGORY').Size := 255; 
     Query.ParamByName('ACTION').Size := 255; 

     Query.Prepare; 

     Query.ParamByName('A_INDEX').Value := 0; 
     Query.ParamByName('CATEGORY').Value := 'Foo'; 
     Query.ParamByName('ACTION').Value := 'Foo'; 

     Query.ExecSQL; // <-- Exception 
    finally 
     Query.Free; 
    end;  
    end; 

enter image description here

난 여전히 SQL에 대해 배우고, 데이터베이스가 날 수있는 이유 & FireDAC 그래서 난 정말 이해가 안 돼요 select 문에 직접 값을 입력하지만 param은 아무 것도하지 않습니다.

그 밖의 방법으로 첫 번째 쿼리를 사용하여 A_INDEX 열에 동적으로 매개 변수를 삽입 할 수 있습니까?

+0

수동으로 매개 변수를 만들거나 "Query.ResourceOptions.ParamCreate : = True;"를 사용합니까? ? – valex

+0

@valex, 내가 자동으로 생성 된 매개 변수를 묻는 질문을 할 때 Vitor는 수동으로 그렇게 제안했지만 변경하지 않았습니다. 내 질문을 전체 코드로 업데이트했습니다. – Peter

+0

지금은 이것을 확인할 수 없지만 'A_INDEX'가 SELECT 목록에 있습니다.예를 들어'INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)로 바꾸십시오. SELECT c.C_ID, 0, a.A_ID, 0 CATEGORY에서 C, ACTIONS는 어디 c_id = : A_INDEX 및 c. NAME = : CATEGORY AND a.NAME = : ACTION' 그리고 나는 오류없이 잘 돌아갈 것이라고 생각합니다. – valex

답변

0

아마도 DFM에서 SQL을 구성 요소에 직접 설정하면 구성 요소의 Params 속성에서 생성 된 매개 변수를 볼 수 있습니다. 모든 매개 변수를 삭제하거나 A_INDEX (정수, 입력)를 수동으로 추가하십시오.

소스 코드에 params를 만들고 ParamCreate 속성을 false로 설정하는 것이 좋습니다. 수동으로 생성해야하는 경우 쉽게 제어 할 수 있습니다.

매개 변수를 수동으로 만들려면 TParams 클래스의 CreateParam 메서드를 사용합니다. 특히 그 표현 SELECT

INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX) 
SELECT c.C_ID, 0, a.A_ID, :A_INDEX 
FROM CATEGORIES c, ACTIONS a 
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION 

을 :

+0

내 모든 쿼리는 로컬 변수이며, 유일한 설계 구성 요소는'TFDConnection'입니다. 나는 당신의 추천을 받아 들였고 수동으로 매개 변수를 만들었고 그 결과는 같습니다. 이 쿼리에 사용하는 완전한 코드로 내 대답을 업데이트했습니다. 당신이 얻고있는 – Peter

+0

오류는 기본적으로 DB이를 실행할 수 있음을 말하고있다 : "여기서 열 = 문자열"나는 당신이 아래의 코드와 피드백에 코드를 변경하는 것이 있습니다 sugest 우리 : Query.ParamByName ('CATEGORY'). 값 : = QuotedStr ('Foo'); Query.ParamByName ('ACTION'). 값 : = QuotedStr ('Foo'); – oPsDCadarn

+0

내 코드에 무엇이 잘못되었는지 알아 내려고 고맙다고 생각하지만 QuotedStr을 사용하는 것은 잘못되었습니다. Params는 문자열을 따옴표로 묶을 것을 기대하지 않으므로 문서에서이를 확인할 수 있습니다. – Peter

1

이 같은 쿼리 변수화 할 수

SELECT c.C_ID, 0, a.A_ID, :A_INDEX 

당신은 전처리 매크로는이 상황을 극복 할 수있는 유일한 방법을,하지만 그들은 작동하지 않습니다 SQL 명령을 수정할 때 실제 쿼리 매개 변수로 사용되므로 DBMS는 명령을 다시 준비해야합니다. 예를 들어

:

procedure Test; 
var 
    Query: TFDQuery; 
begin 
    Query := TFDQuery.Create(nil); 
    try 
    Query.Connection := DBDataModule.dbMain; 

    Query.SQL.Add('INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)'); 
    Query.SQL.Add('SELECT c.C_ID, 0, a.A_ID, &A_INDEX'); // ← & defines macro 
    Query.SQL.Add('FROM CATEGORIES c, ACTIONS a'); 
    Query.SQL.Add('WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION'); 

    Query.ParamByName('CATEGORY').Value := 'Foo'; 
    Query.ParamByName('ACTION').Value := 'Foo'; 
    Query.MacroByName('A_INDEX').AsIdentifier := '0'; 

    Query.ExecSQL; 
    finally 
    Query.Free; 
    end;  
end; 

그러나 A_INDEX 필드 값이 autoincremented 값을해야하는 경우, 그래서처럼 만들

. 또는 다른 테이블의 값인 경우 해당 테이블을 쿼리에 조인하십시오. 매크로는 실제 명령 매개 변수로 작동하지 않으며 준비된 명령을 기대하는 많은 레코드를 삽입 할 때 비효율적 일 수 있습니다.