2012-03-28 8 views
2

現在、C#のソリューションを使用して、OracleからPostgreSQLにデータベーステーブルをコピーしています。 1つのこととは別にすべてがうまくいっています。そのフィールドの1つにSQL文が含まれているテーブルをコピーすると、2つの単一引用符が連続しているために転倒します。 SQL文は、別のプログラムのデータベースには依存しないように使用されているため、テーブルに残っていなければなりません。フィールド値がSQL文である行をプログラムで挿入する

次のSQLを書く方法はありますが、行の終わり近くの 'TRUE'の近くに2つの一重引用符を逆に並べることはありません。私は、C#でステートメントがどのように構築されているかを示すために、以下のコードを追加しました。列はOracleではvarchar2、PostgreSQLではTEXT列です。

EDIT:表示されているSQLの例は、C#コードで生成された実際のINSERT文で、postgresqlデータベース上で実行され、レコードを表に追加します。これは、文字列の形式でSQL文を含むテキストフィールドを挿入するために使用されます。

INSERT INTO SQL_FACTORY_TEST (SQL_FACTORY_TEST_ID,SQL_FACTORY_DIALECT,SQL_FACTORY_QUERY_NAME,SQL_FACTORY_SQL_COMMAND,USER_NAME) 
VALUES (21, 'ORACLE', 'GET_CLUSTERS', 'SELECT CLUSTER_ID, NUM_POINTS, FEATURE_PK, A.CELL_CENTROID.SDO_POINT.X, A.CELL_CENTROID.SDO_POINT.Y, A.CLUSTER_CENTROID.SDO_POINT.X, A.CLUSTER_CENTROID.SDO_POINT.Y, TO_CHAR (A.CLUSTER_EXTENT.GET_WKT()), TO_CHAR (A.CELL_GEOM.GET_WKT()), A.CLUSTER_EXTENT.SDO_SRID FROM (SELECT CLUSTER_ID, NUM_POINTS, FEATURE_PK, SDO_CS.transform (CLUSTER_CENTROID, 4326) cluster_centroid, CLUSTER_EXTENT, SDO_CS.transform (CELL_CENTROID, 4326) cell_centroid, CELL_GEOM FROM :0) a where sdo_filter(A.CELL_GEOM, SDO_CS.transform(mdsys.sdo_geometry(2003, :1, NULL, mdsys.sdo_elem_info_array(1,1003,3),mdsys.sdo_ordinate_array(:2, :3, :4, :5)),81989)) = 'TRUE'', 'PUBLIC') 

コードサンプル:

oleDataBaseConnection.OleExecutePureSqlQuery("SELECT * FROM " + tableName); 

    if (oleDataBaseConnection.HasRows()) 
    { 
     while (oleDataBaseConnection.NextRecord()) 
     { 
      Dictionary<string, string> postgreSQLQueries = TypeConversion.GetQueryDictionary("POSTGRESQL"); 

      string postgreSQLInsertQuery; 

      postgreSQLQueries.TryGetValue("INSERT", out postgreSQLInsertQuery); 

      postgreSQLInsertQuery = postgreSQLInsertQuery.Replace("{0}", tableName); 

      StringBuilder postgresQuery = new StringBuilder(); 

      postgresQuery.Append(postgreSQLInsertQuery); 

      postgresQuery.Append("("); 

      int columnCounter = 0; 

      //add a column parameter to query for each of our columns 
      foreach (KeyValuePair<string, string> t in columnData) 
      { 
       postgresQuery.Append(t.Key + ","); 
       columnCounter++; 
      } 

      postgresQuery = postgresQuery.Remove(postgresQuery.Length - 1, 1); 
      postgresQuery.Append(") "); 

      postgresQuery.Append("VALUES ("); 

      //Loop through values and 

      for (int i = 0; i < columnCounter; i++) 
      { 
       string[] foo = new string[columnData.Count]; 
       columnData.Values.CopyTo(foo, 0); 

       if (foo[i].ToUpper() == "TEXT") 
       { 
        postgresQuery.Append("'" + oleDataBaseConnection.GetFieldById(i) + "', "); 
       } 
       else 
       { 
        postgresQuery.Append(oleDataBaseConnection.GetFieldById(i) + ", "); 
       } 
      } 

      postgresQuery = postgresQuery.Remove(postgresQuery.Length - 2, 2); 
      postgresQuery.Append(") "); 
      postgresSQLDBConnection.PostgreSQLExecutePureSqlNonQuery(postgresQuery.ToString()); 
     } 
    } 

答えて

1

最善の解決策は、あなたが直接リテラルを渡すことはありませんPreparedStatementを使用することです。私はC#を知らないので、その例を挙げることはできません。あなたがそのような声明を維持するを持っている場合

ただし、PostgreSQLのリテラル「dollar quoted」の文字列を使用することができます。

INSERT INTO SQL_FACTORY_TEST (SQL_FACTORY_TEST_ID,SQL_FACTORY_DIALECT,SQL_FACTORY_QUERY_NAME,SQL_FACTORY_SQL_COMMAND,USER_NAME) 
VALUES (21, 'ORACLE', 'GET_CLUSTERS', $$ ...... 'TRUE'$$, 'PUBLIC') 

$$はリテラルの周りの一重引用符を置き換えます。あなたの価値に$$が含まれている可能性がある場合は、それに固有の識別子を追加することもできます。

$42$String with embedded single quotes ''' and two $$ dollar characters$42$ 
+0

INSERT INTO FOO(bar、foobar)VALUES( 'bar'、 'foobar')がINSERT INTO FOO(bar、foobar)VALUESに変更されるような文字列リテラルをすべて表すために、 ($$ bar $$、$$ foobar $$)?これは、クエリ文字列の構築コードで '$$'を置き換えるためのC#コードの単純な修正となります。 postgresQuery.Append( "'" + oleDataBaseConnection.GetFieldById(i)+ "'、"); はpostgresQuery.Append( "$$" + oleDataBaseConnection.GetFieldById(i)+ "$$")になります。 – CSharpened

+0

はい、これは一重引用符の代わりに使用できます。私が掲示したマニュアルへのリンクを読んでください。 –

+0

ありがとうございました。そのリンクをチェックアウトします。気づかなかった – CSharpened

0

データベースに格納されている値を正しくエスケープし、エスケープする必要があります。

PostgreSQLクライアントライブラリは、この目的のためにPQescapeLiteral関数を提供します。

1

ベストプラクティスは、パラメータ化された挿入クエリを使用することです。

INSERT INTO [Table] VALUES (@Column1, @Column2, @Column3) 

次に、変数をクエリに渡します。線に沿って何か:

List<OleDbParameter> parameters = new List<OleDbParameter>(); 
      for (int i = 0; i < columnCounter; i++) 
      { 
       postgresQuery.Append(string.Format("@Column{0}, ", i)); 
       parameters.Add(new OleDbParameter(string.Format("@Column{0}, ", i), oleDataBaseConnection.GetFieldById(i)); 
      } 

は次に、あなたのOleDbCommandの実行にparemeters.ToArray()を渡します。これは、C#がすべてのエスケープ処理を行い、あなたのためにデータ型を処理することを意味します。あなたのニーズに合わせて微調整する必要があるかもしれませんが、一般的な要点はそこにあります。

+0

ありがとう私はこの解決策を非常に気に入っており、以前はデータベースに依存しないバインド変数に似たようなことをしてきました。もし彼が実装するのがはるかに速く、私はタイムスケールにいるので、a_horse_with_no_nameの解決策ではそれを修正しなければ、私はそれを調べるでしょう。必要に応じてこのソリューションに修正することができます。 – CSharpened

関連する問題