从选择查询+变量值插入表
Posted
技术标签:
【中文标题】从选择查询+变量值插入表【英文标题】:Insert into table from select query + variables values 【发布时间】:2014-01-29 15:31:18 【问题描述】:我想在表 tb2(QuestionID、QuestionStem、UserID、ExamID)中插入一组从表 tb1(QuestionID、QuestionStem)中随机选择的行以及两列 UserID、ExamID 的值,这些列对于一次插入是固定的询问。我已在 webmatrix 中尝试过此查询,但在插入查询语句中出现 @ 不应位于此位置的错误:
db.Query("INSERT INTO tb2 (QuestionID, QuestionStem, UserID, ExamID) SELECT QuestionID, QuestionStem, @UserID, @ExamID FROM tb2");
感谢任何帮助。我正在使用 webmatrix 3.0 来构建我的应用程序。 请注意,插入后的 UPDATE 语句将不起作用,因为将有同时存在的用户,我想根据每个用户的 UserID 和 ExamID 显示选定的行。
【问题讨论】:
【参考方案1】:您无法在 Webmatrix 中使用单个参数化查询来完成您的任务,而且在我看来,创建连接参数的查询并不是一个好的解决方案。
更好的选择是从表 t1 中提取您需要的记录,并使用 foreach 循环将它们一一插入:
@
var userId = 25;
var examId = 32;
var sql1 = "SELECT TOP 10 QuestionID, QuestionStem FROM t1 ORDER BY NEWID()";
var sql2 = @"INSERT INTO tb2 (QuestionID, QuestionStem, UserID, ExamID)
VALUES (@0, @1, @2, @3)";
var db = Database.Open("yourDb");
var data = db.Query(sql1);
foreach (var row in data)
db.Execute(sql2, row.QuestionID, row.QuestionStem, userId, examId);
已编辑
如果性能是一个真正的问题,也许最好的解决方案是将数据从 Sql Server Compact 迁移到 Sql Server Express。
在这种环境下,您可以创建像
这样的存储过程CREATE PROCEDURE AddQuestions @UserID int, @ExamID int
AS
INSERT INTO dbo.tb2 (QuestionID, QuestionStem, UserID, ExamID)
SELECT TOP 10 QuestionID, QuestionStem, @UserID AS UserID, @ExamID AS ExamID
FROM dbo.t2 ORDER BY NEWID()
GO
并在 WebMatrix 中调用它:
@
var userId = 14;
var examId = 16;
var db = Database.Open("yourDb");
var data = db.Execute("EXEC AddQuestions @UserID = @0, @ExamID = @1",
userId, examId);
【讨论】:
不同意您的回答,因为我理解避免串联的愿望,但这种方法比我的回答效率低一个数量级。只要您了解风险并在更一般的意义上知道您在做什么,我认为将类型安全整数连接到命令中没有问题。对于流量很少的网站上只有 10 行,这种方法更好,因为它可以避免“危险”的地面,但如果sql1
选择数千行,则可能需要几秒钟而不是几毫秒才能完成。
@Polynomial,我同意你的观点,我的解决方案比你的效率低,但是,如果性能是一个问题,也许 Sql Server Compact 不是正确的选择。我已经编辑了我的答案。
一个公平的观点,您的编辑值得一票。公平地说,这个问题并没有具体说明他们使用的是什么 SQL 版本(我知道你可以从我的答案的评论中推断出来,但问题本身就足够笼统了),我会说它总是值得通过每种方法的相对优缺点。程序员能够做出明智的决定总是更好。
感谢您非常有建设性的 cmets。【参考方案2】:
如果我理解正确,您可以对这两个参数使用编号的序数。像这样,但设置变量以使用您的数据当然是适当的:
var userId = 0;
var examId = 0;
db.Query("INSERT INTO tb2 (QuestionID, QuestionStem, UserID, ExamID) SELECT QuestionID, QuestionStem, @0, @1 FROM tb1", userId, examId);
您还提到您希望随机选择来自tb1
的行。您可以通过将ORDER BY NEWID()
添加到查询中SELECT
语句的末尾来实现此目的:
db.Query("INSERT INTO tb2 (QuestionID, QuestionStem, UserID, ExamID) SELECT QuestionID, QuestionStem, @0, @1 FROM tb1 ORDER BY NEWID", userId, examId);
如果您只想将其限制为多行(例如,十行):
db.Query("INSERT INTO tb2 (QuestionID, QuestionStem, UserID, ExamID) SELECT TOP 10 QuestionID, QuestionStem, @0, @1 FROM tb1 ORDER BY NEWID", userId, examId);
【讨论】:
它没有用。错误消息:此位置不允许有参数。确保“@”符号位于有效位置或此 SQL 语句中的参数完全有效。说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。异常详细信息:System.Data.SqlServerCe.SqlCeException:此位置不允许参数。确保“@”符号位于有效位置或此 SQL 语句中的参数完全有效。 我猜你可以直接将参数连接到字符串中,注意避免注入黑客向量(这应该很容易,因为它们都是整数值)。以上是关于从选择查询+变量值插入表的主要内容,如果未能解决你的问题,请参考以下文章