我有如下的sql语句:
Select i.imageID, theImage, translationRating
From images i
inner join translationchains t
on t.imageId = i.imageid
where i.userID=(someUserID) And i.translated =0
and t.targetLang in (select targetLang from translationChains)
我想让它成为在我的 java 代码中使用的准备好的语句:
Select i.imageID, theImage, translationRating
From images i
inner join translationchains t
on t.imageId = i.imageid
where i.userID=? And i.translated =0
and t.targetLang in (select ? from translationChains)
第一个的输入?是一个用户 ID(整数),它工作正常。
第二个输入是一个包含 languageId 的字符串 - 它是一个包含表示语言的数字的字符串,或者包含列名称的字符串“targetLang”(=所有语言)
在我的 java 代码中我做了以下事情:
Image.setInt(1, userID);
Image.setString(2, langID);
Image.executeQuery()
我的问题是当我发送字符串“targetLang”作为第二个参数时 准备好的语句将其作为“targetLang”(带有“之前和之后”)插入,对于数字这不是问题,因为 3='3',但是对于字符串,它给出了与我需要的不同的结果——我总是得到一个空结果集,因为没有任何内容等于“targetLang”。 我需要将这个字符串插入到没有 '. 有可能还是我需要使用不同于准备好的语句的东西?
我知道我可以构建一个包含所有这些查询的字符串,但我正在寻找更优雅的东西 发送
编辑:
这是创建表 translationChains:
Create Table if not exists TranslationChains (
ImageID int (10) NOT NULL,
SourceLang int NOT NULL,
TargetLang int NOT NULL,
Translated tinyint default 0,
Translation text,
Translator varchar (30),
CONSTRAINT translate_image PRIMARY KEY (ImageID,SourceLang, TargetLang),
FOREIGN KEY (ImageID) REFERENCES Images(ImageID) ON DELETE CASCADE,
FOREIGN KEY (SourceLang) REFERENCES Languages(languageID) ON DELETE CASCADE,
FOREIGN KEY (TargetLang) REFERENCES Languages(languageID) ON DELETE CASCADE)
如您所见,我正在尝试根据“targetLang”列(一个 int 列)拍摄图像。每个数字代表一种语言。
现在我有两个选项可以从该表中选择图像:
所以我不是在与固定字符串“targetLang”进行比较。我想为此列选择所有可能的值(从 translationChains 中选择 targetLang)。
最佳答案
查询参数只能代替文字值——即您通常放置带引号的字符串文字、带引号的日期文字或数字文字的地方。因此,字符串值总是被解释为字符串文字,就好像您用单引号将它放入查询中一样。
对于列名、表名、SQL 表达式、SQL 关键字等,您必须在调用 prepare() 之前将这些值插入到 SQL 查询中。
为了最安全,请使用白名单,这样用户输入就不会逐字插入到 SQL 查询中。在查询中使用之前始终验证用户输入(或任何其他内容)。
我有written many examples构建 SQL 查询时的白名单。
您还可以在我的演示文稿中查看示例 SQL Injection Myths and Fallacies和我的书 SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming .
回复你的评论:
我不确定你在做什么。听起来您要么希望 t.targetLang 等于文字数字,要么希望固定字符串 'targetLang'。如果是这样,我根本不知道您为什么要执行子查询——您应该只使用一个查询参数作为一个值:
where i.userID = ? And i.translated = 0
and t.targetLang = ?
Image.setString(2, langID); // either '3' or 'targetLang'
但我不确定我是否完全理解您的描述。该数字是否代表您要比较的列的位置?与 t.targetLang 在同一行?如果是这样,我仍然认为您不需要子查询。您可以使用如下表达式:
where i.userID = ? And i.translated = 0
and FIELD(t.targetLang, t.targetLang, t.column2, t.column3, t.column4) = ?
Image.setString(2, '1'); // for the case where you allow all langs
Image.setString(2, '3'); // for the case where you want to match a specific column.
请参阅 FIELD() 上的手册MySQL 中的函数,它在表达式列表中搜索第一个参数。它返回匹配的字段的整数位置。
使用此方法,您可以传递您希望 t.targetLang 匹配的位置,这允许您将动态部分作为值而不是列名传递。它还允许您避免子查询。
如果我仍然有误并且不理解您的问题,请编辑您的原始问题并提供更多详细信息。 SHOW CREATE TABLE translationChains 会有所帮助。你也能回答一些我不得不做出假设的事情吗?您是否尝试将 t.targetLang 与另一列中的值进行匹配在同一行?
好的,现在我更了解你的目标了。这是一个执行您想要的操作的查询:
SELECT i.imageID, theImage, translationRating 来自图像我 INNER JOIN 翻译链 t ON t.imageId = i.imageid 哪里 i.userID = ? AND i.translated = 0 和 ? IN (t.targetLang, 'targetLang')
您可以作为第二个参数传递一个与 t.targetLang 匹配的整数,或者将与谓词中的值 'targetLang' 匹配的文字字符串“targetLang”。
不过,我不推荐这个解决方案,因为它可能不会很好地使用索引,它可能必须通过将字符串参数与整数列进行比较来执行类型转换。
当您想要匹配所有语言时,更好的做法是在 WHERE 子句中不带执行查询的最后一项。也就是说,在您的应用程序中,仅当您希望查询获取特定语言时,才有条件地附加该术语。否则,省略该术语并跳过 Image.setString()。
String sql = "SELECT i.imageID, theImage, translationRating
FROM Images i
INNER JOIN TranslationChains t
ON t.imageId = i.imageid
WHERE i.userID = ? AND i.translated = 0 ";
if (langId) {
sql += " AND ? IN (t.targetLang, 'targetLang')";
}
. . .
Image.setInt(1, userID);
if (langId) {
Image.setString(2, langID);
}
Image.executeQuery()
关于mysql - 在没有 ' ' 的情况下将字符串插入准备好的语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15818819/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%