2012-03-28 8 views
2

Ich arbeite derzeit an einer Lösung in C# Datenbank-Tabellen gegenüber Oracle auf PostgreSQL zu kopieren. Alles funktioniert gut, abgesehen von einer Sache. Wenn ich eine meiner Tabellen, die SQL-Anweisungen in einem ihrer Felder enthalten, kopieren, fällt sie aufgrund von zwei einfachen Anführungszeichen auf. Die SQL-Anweisungen MÜSSEN in der Tabelle verbleiben, da sie verwendet wird, um eine andere Programmdatenbank agnostisch zu machen.Programatically Einfügen von Zeilen, in denen Feldwert SQL-Anweisung ist

Gibt es eine Möglichkeit die folgenden SQL zu schreiben, aber die beide einfachen Anführungszeichen zurück, ohne gesehen in der Nähe des ‚TRUE‘ Wert nahe dem Ende der Leitung zu unterstützen. Ich habe auch meinen Code unten eingefügt, um zu zeigen, wie die Anweisung in C# aufgebaut ist. Die Spalte ist ein varchar2 in Oracle und eine TEXT-Spalte in PostgreSQL.

BEARBEITEN: Das sql-Beispiel ist die tatsächliche INSERT-Anweisung, die von meinem C# -Code generiert wird, der dann in der postgresql-Datenbank ausgeführt wird, um einen Datensatz zu einer Tabelle hinzuzufügen. Es wird unter anderem verwendet, um ein Textfeld einzufügen, das eine SQL-Anweisung in Form einer Zeichenfolge enthält.

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') 

Codebeispiel:

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()); 
     } 
    } 

Antwort

1

Die beste Lösung ist ein PreparedStatement zu verwenden, wo Sie Literale nicht direkt übergeben. Ich kenne C# nicht, also kann ich dir dafür kein Beispiel geben.

Wenn Sie jedoch haben, um die Aussage so zu halten, können Sie ein "dollar quoted" String-Literal in PostgreSQL verwenden.

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') 

Das $$ ersetzt die einzelnen Anführungszeichen um das Literal. Wenn die Wahrscheinlichkeit besteht, dass Ihr Wert $$ enthält, können Sie ihm auch einen eindeutigen Bezeichner hinzufügen, z.

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

Kann diese $$ Lösung verwendet werden, um alle meine String-Literale zu bezeichnen, so dass INSERT INTO FOO (bar, foobar) VALUES ('bar', 'foobar') in INSERT INTO FOO (bar, foobar) WERTE geändert werden würde ($$ bar $$, $ $ foobar $$)? Dies wäre eine einfache Korrektur im C# -Code, um '' mit $$ 'im Konstruktionscode der Abfragezeichenfolge zu ersetzen. Die Zeile postgresQuery.Append ("'" + oleDataBaseConnection.GetFieldById (i) +' ', "); würde postgresQuery.Append ("$$" + oleDataBaseConnection.GetFieldById (i) + "$$"); – CSharpened

+0

Ja, dies kann anstelle von einfachen Anführungszeichen verwendet werden. Lies den Link zu dem Handbuch, das ich gepostet habe. –

+0

Ausgezeichnet danke. Werde diesen Link auschecken. Ich habe es nicht bemerkt. – CSharpened

0

Sie sollten die Werte, die in der Datenbank gespeichert sind, immer ordnungsgemäß entwischen und nicht anzeigen.

Die PostgreSQL-Client-Bibliothek bietet die PQescapeLiteral Funktion für diesen Zweck.

1

Ich denke, der beste Ansatz ist es, eine parametrisierte INSERT-Abfrage zu verwenden. so erstellen Sie eine Abfrage wie:

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

dann übergeben Sie die Variable in die Abfrage. Etwas entlang der Linien von:

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)); 
      } 

Dann paremeters.ToArray() an Sie weitergeben OleDbCommand bei der Ausführung. Das bedeutet, dass C# alle Daten entnimmt und den Datentyp für Sie ausarbeitet. Es bedarf vielleicht ein wenig Feinabstimmung, um Ihren Bedürfnissen zu entsprechen, aber der allgemeine Kern davon ist da.

+0

Danke Ich mag diese Lösung und habe etwas Ähnliches vorher für Datenbank-agnostische Bind-Variablen getan. Ich werde es untersuchen, wenn die Lösung von a_horse_with_no_name es nicht repariert, da es viel schneller zu implementieren ist und ich auf einer Zeitskala bin. Ich kann es nach Bedarf zu dieser Lösung überarbeiten. – CSharpened

Verwandte Themen