我想创建一个JDBC PreparedStatement,如:
SELECT URL,LOCATE ( '?', URL ) pos FROM Links WHERE pageId=? ORDER BY pos ASC
第一个?
是文字,第二个?
是参数。我可以使用CHAR(63)
代替'?'
,但我认为额外的函数调用会减慢SQL执行速度。有没有办法逃脱第一个?
?
编辑:
以下代码测试dkatzel的断言,即字符串中的?
字符不被视为标记:
public class Test {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:mem:test");
Statement stmt = conn.createStatement();
stmt.executeUpdate("CREATE TABLE Links(URL VARCHAR(255) PRIMARY KEY,pageId BIGINT)");
stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar?baz',1)");
stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar/baz',1)");
stmt.close();
PreparedStatement ps = conn
.prepareStatement("SELECT URL,LOCATE ( '?', URL ) pos FROM Links WHERE pageId=? ORDER BY pos ASC");
ps.setLong(1, 1);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1) + ":" + rs.getInt(2));
}
rs.close();
ps.close();
conn.close();
}
}
输出:
http://foo.bar/baz:0
http://foo.bar?baz:15
看来dkatzel是正确的。我搜索了JDBC Spec并且找不到任何提及?
参数标记如果在引号内会被忽略,但是我找到的PreparedStatement解析器的几个实现(MySql,{ {3}},c-JDBC)似乎都将单引号中的文本排除在考虑范围之外作为参数标记。
答案 0 :(得分:10)
根据您使用的JDBC驱动程序,您可以通过添加其他问号来逃避,例如:如果你正在使用PostgreSQL
https://jdbc.postgresql.org/documentation/head/statement.html
在JDBC中,问号(
?
)是PreparedStatement的位置参数的占位符。但是,有许多PostgreSQL运算符包含问号。要使SQL语句中的此类问号不被解释为位置参数,请使用两个问号(??
)作为转义序列。您也可以在Statement中使用此转义序列,但这不是必需的。特别是在语句中,单个(?
)可以用作运算符。
答案 1 :(得分:6)
如果它不能与您的JDBC驱动程序一起使用,您可以将其绑定为String
?
,
ps.setString(1, "?");
答案 2 :(得分:4)
?
的含义在SQL规范中指定,JDBC规范遵循SQL规范。
驱动程序不会(并且不应该)将文字中的问号解释为参数占位符,因为字符串文字中的问号只是字符串文字中的字符。有关更多信息,请参阅SQL:2011 Foundation(ISO-9075-2:2011)的第5章。
因此没有必要(也不可能)逃避。
答案 3 :(得分:3)
答案 4 :(得分:2)
我在查询中使用了CHR(63),这有助于解决我的问题。
以下是我所做的例子:
$http.get(api.getUrl('latestActivityByTeamAndModule', [$scope.team_id, $scope.module_id]))
.success(function(response){
var i = 0;
$scope.line = [];
$scope.categories = [];
response.forEach(function(y){
var log_date = y.date.substr(0, y.date.indexOf('T'));
var date = new Date(log_date);
var logg_date = moment(date).fromNow();
$scope.categories.push(logg_date);
$scope.line.push(y.num_taken);
});
});
这有助于获取字符串:
<div id="test" ui-jq="plot" ui-options="[
{ data: [4], points: { show: true, radius: 6}, splines: { show: true, tension: 0.45, lineWidth: 5, fill: 0 }, label: 'Akademi' },
],
{
colors: ['#23b7e5', '#27c24c'],
series: { shadowSize: 3 },
xaxis:{
font: { color: '#ccc' },
position: 'bottom',
ticks: ["21 hours ago"]
},
yaxis:{ font: { color: '#ccc' } },
grid: { hoverable: true, clickable: true, borderWidth: 0, color: '#ccc' },
tooltip: true,
tooltipOpts: { content: '%x.1 is %y.4', defaultTheme: false, shifts: { x: 0, y: 20 } },
redrawOverlayInterval: 60
}" style="height: 240px; padding: 0px; position: relative;">
然后我在insert语句中使用了这个查询,并运行了PreparedStatement。工作得非常好。
CHR函数是一个内置函数,可以像其他oracle函数一样使用。如果您知道查询将不会重复多次,您可以使用它。