2015-01-14 28 views
0

我試圖執行從C#中的parametrised查詢工作,我得到的錯誤:解析錯誤從C#parametrised查詢,但在的pgAdmin III

ERROR: XX000: parse error - invalid geometry

與提示

"POLYGON((:m" <-- parse error at position 11 within geometry

但當我在pgAdmin III中運行查詢並用它們的值替換參數時,查詢就起作用了。該代碼是

command.CommandText = "SELECT area_code FROM area WHERE ST_INTERSECTS(ST_GeographyFromText('POLYGON((:minx :miny, :minx :maxy, :maxx :maxy, :maxx :miny, :minx :miny))'), shape) AND area_type_code = :typecode"; 
command.CommandType = CommandType.Text; 
var typeCodeParameter = new NpgsqlParameter 
{ 
    DbType = DbType.String, 
    ParameterName = "typecode", 
    Value = _typeCode 
}; 
var minxParameter = new NpgsqlParameter 
{ 
    DbType = DbType.Double, 
    ParameterName = "minx", 
    Value = _minX 
}; 
var minyParameter = new NpgsqlParameter 
{ 
    DbType = DbType.Double, 
    ParameterName = "miny", 
    Value = _minY 
}; 
var maxxParameter = new NpgsqlParameter 
{ 
    DbType = DbType.Double, 
    ParameterName = "maxx", 
    Value = _maxX 
}; 
var maxyParameter = new NpgsqlParameter 
{ 
    DbType = DbType.Double, 
    ParameterName = "maxy", 
    Value = _maxY 
}; 
command.Parameters.Add(typeCodeParameter); 
command.Parameters.Add(maxxParameter); 
command.Parameters.Add(maxyParameter); 
command.Parameters.Add(minxParameter); 
command.Parameters.Add(minyParameter); 
using (var reader = command.ExecuteReader()) 
    while (reader.Read()) 
     areas.Add((string)reader["area_code"]); 

和工作查詢

SELECT area_code FROM area WHERE ST_INTERSECTS(ST_GeographyFromText('POLYGON((-1.0042576967558934 50.78431084582985, -1.0042576967558934 51.199216033050647, 1.9400782407441057 51.199216033050647, 1.9400782407441057 50.78431084582985, -1.0042576967558934 50.78431084582985))'), shape) AND area_type_code = 'County' 

我在做什麼錯?我應該如何設置minx,miny,maxx,maxy參數?

回答

2

問題是你正在分離座標。這些參數不只是在SQL內部放在一起(它不只是一個模板替換),它需要是一個語法上有效的放置參數的地方。良好的完整性檢查是嘗試相同的查詢,而不是直接用值替換參數,而是使用過程SQL和變量。

您將看到問題在於ST_GeographyFromText函數不會擴展輸入字符串中的參數 - 這是預期的行爲。如果你想使用這個函數,你不能在字符串中使用參數 - 你仍然需要把所有的值都傳遞給它們,並把它們作爲一個字符串傳遞 - 這與你在「刪除參數」時所做的相同。最簡單的解決方案可能是將整個字符串作爲參數傳遞,或者只是將參數添加到查詢中的字符串中(例如ST_GeographyFromText('POLYGON((' || cast(:minx ...) || '), ' || ... || ')')等)

看起來好像你在轉換舊的「連接一串字符串「SQL與參數化查詢。要堅持下去,但你需要考慮語法。就像你不能只在一個參數中放置一個子查詢一樣,你不能將一個單獨的值分成兩個這樣的參數。所以你需要使用更好的類型,或者有一些幫助者轉換(比如一個函數需要兩個浮點數,然後返回你需要的類型)。

+0

謝謝,這是有道理的。我已經想出了一個解決方法,我使用string.Format將座標參數放入SQL字符串中。這應該是從SQL注入安全的,因爲它們是double類型的,所以沒有什麼討厭的東西可以進入SQL命令。 –

+0

@AndyNichols您實際上不需要直接將其放入SQL字符串中 - 只需將「ST_GeographyFromText」的整個參數作爲單個字符串參數傳遞即可。除非'ST_GeographyFromText'函數確實有些奇怪,否則它應該是完全安全的,並且您將獲得執行計劃的重用。 – Luaan

1

使用此參數化查詢的正確方法是使用帶數字參數來構建信封的函數,如ST_MakeEnvelope(xmin, ymin, xmax, ymax)

SELECT area_code 
FROM area 
WHERE ST_Intersects(ST_MakeEnvelope(:minx, :miny, :maxx, :maxy)::geography, shape) 
    AND area_type_code = :typecode; 

格式化文本(WKT)的其它嘗試是較慢的和有損的,因爲這些數字被轉換爲文本,然後解析回數字。