我目前正在研究C#中的解决方案,以便将数据库表从Oracle复制到PostgreSQL。除了一件事,一切都很好。当我复制其中一个包含sql语句的表时,由于有两个单引号背靠背而导致其崩溃。 SQL语句必须保留在表中,因为它用于使另一个程序数据库不可知。
有没有办法编写以下SQL,但没有在行尾的“TRUE”值附近看到两个单引号。我还在下面包含了我的代码,以显示如何在C#中构建语句。该列是Oracle中的varchar2和PostgreSQL中的TEXT列。
编辑:显示的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());
}
}
答案 0 :(得分: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$
答案 1 :(得分: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));
}
然后在执行时将paremeters.ToArray()
传递给OleDbCommand。这意味着c#将执行所有转义,并为您计算出数据类型。它可能需要一些调整以满足您的需求,但它的一般要点就在那里。
答案 2 :(得分:0)
您应该始终正确地逃避和取消存储在数据库中的值。
PostgreSQL客户端库为此提供PQescapeLiteral功能。