문제

나는 두 가지 문제에 직면하고 있습니다 ...

(1) Delphi XE6을 사용하여 데이터베이스 (SQLite)에 쓸 때 항상 데이터베이스가 잠긴 오류 메시지가 표시됩니다.명령을 사용하여 데이터베이스를 닫으면 데이터베이스를 닫았습니다. fdconnection1.close;

(2) 들어오는 매개 변수에서 테이블에 어떻게 삽입합니까? 나는 다음과 같은 들어오는 매개 변수가있다

procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);
.

다음 SQL 명령으로 테이블에 쓰려고 시도했습니다.

sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell,
         Price_Per_Share, Num_Shares, Trans_Fee) 
         VALUES (Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share,  
         Num_Shares, Trans_Fee)';
.

하지만 작동하지 않는 것 같지 않습니다 ...

다음은

에 문제가있는 완전한 절차입니다.
procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
  Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);
var
  query : TFDQuery;
  sSQL: string;
begin
    query := TFDQuery.Create(nil);
  try
    ConnectToSQLite;
    query.Connection := FDConnection1;
  if Stock_Code.IsEmpty then
    ShowMessage('Stock Code Cannot Be Empty')
    else
      if Stock_Name.IsEmpty then
        ShowMessage('Stock Name Cannot Be Empty')
        else
          if Tran_Date.IsEmpty then
            ShowMessage('Transaction Date Cannot Be Empty')
            else
            begin
//              sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee) VALUES (Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee)';
              sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee) VALUES (1,2,3,4,5,6,7)';
              query.sql.Text := sSQL;
              query.ExecSQL;
              query.Open();
        end;
  finally
    query.Close;
    query.DisposeOf;
    DisconnectFromSQLite;
  end;

end;
.

모든 힌트는 매우 높이 평가됩니다.미리 감사드립니다.

도움이 되었습니까?

해결책

동적 SQL 문을 실행하는 데는 두 가지 기술이 있습니다. 그러나 나는 더 짧은 SQL을 사용하여 논리에 집중할 수 있습니다 :

순수한 방법 (파라미터 사용)

q.SQL.Text:=
  'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) '+
  'VALUES (:Stock_Code, :Stock_Name)';
q.Prepare; //Optional
q.ParamsByName('Stock_Code').AsString := Stock_Code;
q.ParamsByName('Stock_Name').AsString := Stock_Name;
q.ExecSQL;
.

더러운 방식 (건물 SQL)

q.SQL.Text:=
  'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) VALUES ('+
  QuotedStr(Stock_Code) + ', '+
  QuotedStr(Stock_Name) + ')';
q.ExecSQL;
.

차이점은 중요합니다. 더러운 방법은 SQL 주입 문제 (대부분의 다른 언어에서는 SQL을 빌드하지만 매개 변수없이)로 노출합니다. 이것은 당신을위한 문제 일 수도 있고 그렇지 않을 수 있습니다. 절차가 자신의 코드로 비공개로만 호출되었는지, 그 절차 매개 변수 값은 좋은 값을 포함 할 수 있거나 SQL을 작성하고 실행하기 전에 좋은 매개 변수 검사를 수행하는 경우 ... 귀하는 안전합니다. .

그러나 매개 변수 (순수한 방식)로 수행하면 매개 변수 값을 알지 못하면 SQL 문이 엔진에 의해 유효성이 검사되므로 SQL 주입에서 자동으로 보호됩니다. 따라서 SQL 문 구조체는 엔진이 알고 있으며 실제 값으로 변경할 수 없습니다.

또 다른 고려 사항은 해당 INSERT 문을 자주 실행하는 빈도입니다. 순수한 방법으로 쿼리를 한 번 준비하고 다른 매개 변수 값으로 여러 번 실행할 수 있습니다 (쿼리 개체를 파괴해서는 안되며 SQL 속성을 변경하지 않아야하며 준비 방법을 한 번 호출해야합니다). 루프 내에서 자주 실행하면 더러운 방식으로 SQL을 여러 번 빌드하는 것보다 효율적일 수 있습니다. OTOH 하나의 행을 삽입 해야하는 경우, 조금 더 많은 오버 헤드를 포즈 할 수 있습니다.

=================

adide ... CL은 맞습니다 ... 그 값은 문자열이 아니어야합니다. 매개 변수 객체에는 다른 데이터 유형을 처리하는 데 많은 속성이 있습니다.

  q.ParamsByName('somedate').AsDateTime := Date;
  q.ParamsByName('somenumeric').AsFloat := 3/4;
.

... 등등.

매개 변수를 사용하지 않으면 상황이 어려워집니다. Quotestr 함수는 문자열에 좋지만 날짜와 통화 및 다른 가치 유형을 구울 때 SQL에서 직접 사용할 수있는 것이 무엇인지 알아야합니다. 여러 가지 문제가 발생할 수 있습니다 ... 세계의 반대쪽 끝에있을 수있는 서버와 comunication에 적합하지 않거나 그런 식으로 포맷 된 값을 읽을 수 없을 수도 있습니다. 엔진 특정 서식 및 변환 문제를 처리해야 할 수 있습니다.

매개 변수를 사용하는 경우 Firedac은이 모든 것을 관리해야합니다.)

다른 팁

쿼리에 값을 가져 오려면 매개 변수를 사용하십시오 (이는 문서 ) :

query.SQL.Text := 'INSERT INTO Each_Stock_Owned'+
                    '(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, '+
                     'Price_Per_Share, Num_Shares, Trans_Fee) '+
                    'VALUES (:sc, :sn, :td, :bs, :pps, :ns, :tf)';
query.ParamByName('sc').AsString := Stock_Code;
query.ParamByName('sn').AsString := Stock_Name;
query.ParamByName('td').AsString := Tran_Date;
query.ParamByName('bs').AsString := Buy_Sell;
query.ParamByName('pps').AsString := Price_Per_Share;
query.ParamByName('ns').AsString := Num_Shares;
query.ParamByName('tf').AsString := Trans_Fee;
query.ExecSQL;
.

(그리고이 모든 가치가 실제로 문자열이어야합니다 ...)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top