SQL 服务器:使用 select 和其他参数插入
Posted
技术标签:
【中文标题】SQL 服务器:使用 select 和其他参数插入【英文标题】:SQL server: insert into using select and other parameter 【发布时间】:2014-06-11 22:32:03 【问题描述】:我有 3 个表:projects、managers 和 project_manager
经理
manager_id (int, PK) 经理姓名项目
project_id (int, PK) 项目名称project_manager
project_id (int, PK) manager_id (int, PK)假设经理当前已登录(因此我们知道 manager_id 是什么)并且他想通过在 txtName 文本框中输入名称来创建一个新的 Project并点击“创建”按钮。我试着写:
(1) 将新项目(名称)插入到 projects 表和
中的查询(2) 将 project_id 和 manager_id 插入 project_manager 表的单个查询
但在第三个查询字符串出现语法错误,这不是一个好方法,因为插入项目表(查询 1)可能会成功,但插入其他表(查询 2)可能会失败,我不太了解“高级”东西”的SQL,肯定需要帮助:
string CS = ConfigurationManager.ConnectionStrings["CTECS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
string q1 = "SELECT COUNT(*) FROM [projects] WHERE project_name = @Name";
SqlCommand cmd = new SqlCommand(q1, con);
cmd.Parameters.AddWithValue("@Name", txtName.Text);
con.Open();
int i = (int)cmd.ExecuteScalar();
if (i < 1)
string Command = "INSERT INTO [dbo].[projects] (project_name) VALUES (@Name)";
cmd = new SqlCommand(Command, con);
cmd.Parameters.AddWithValue("@Name", txtName.Text);
cmd.ExecuteNonQuery();
Command = "INSERT INTO [project_manager] (project_id, manager_id) VALUES (SELECT project_id FROM [projects] WHERE project_name = @Name, @ID)";
cmd = new SqlCommand(Command, con);
// Provide the value for the parameter
cmd.Parameters.AddWithValue("@Name", txtName.Text);
cmd.Parameters.AddWithValue("@ID", currentUser.userID.ToString());
cmd.ExecuteNonQuery();
else
Panel1.Visible = true;
lblMessage.CssClass = "alert alert-error";
lblMessage.Text = "This project's name has been already used.";
return;
【问题讨论】:
不,这是对的,我的错.. 【参考方案1】:我觉得第三条sql语句应该是:
INSERT INTO [project_manager] (project_id, manager_id) SELECT project_id, @ID FROM [projects] WHERE project_name = @Name
【讨论】:
如果他有多个同名项目,他最终会在表中插入多条记录。 同意。最好的方法是在插入 [projects] 后使用 SCOPE_IDENTITY() 来获取 project_id(假设 project_id 是一个标识列) @MikeHixson 你能否给出一个完整的答案来解释你的想法,我很难弄清楚? @RonaldinhoState 你的原始帖子在你编辑它之前说:“我试过这个,但在第三个查询字符串出现语法错误”。我的答复是对那个声明。如果你用我的回答中的那个替换你的第三个 sql 语句,它应该会处理你的语法错误。 @MikeHixson 我的意思是您在评论中提到的使用 SCOPE_IDENTITY() 的“更好”想法【参考方案2】:您是否在单用户模式下使用服务器?我不这么认为。首先,您必须在事务中执行此操作。最好的方法-SP。检查项目是否存在并不能保证插入时它不存在。
CREATE PROC usp_InsertProject(@project_name varchar(255), @manager_id int)
AS
SET NOCOUNT ON
DECLARE @project_id int
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[projects] (project_name) VALUES (@project_name)
SELECT @project_id = SCOPE_IDENTITY()
INSERT INTO [project_manager] (project_id, manager_id)
VALUES(@project_id, @manager_id)
COMMIT TRAN
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_MESSAGE() AS ErrorMessage
ROLLBACK TRAN
END CATCH
GO
然后
string CS = ConfigurationManager.ConnectionStrings["CTECS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
SqlCommand cmd = new SqlCommand("usp_InsertProject", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@project_name", txtName.Text); // you must validate text value before passing
cmd.Parameters.AddWithValue("@manager_id", currentUser.userID);
con.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
if(reader.Read())
// the error occured in SP
// reader[0] is error number
// record[1] is error message
【讨论】:
我很难理解这个答案,但我会研究“事务”SQL。 注意,如果你想避免项目名称重复,你必须对projects.project_name
有唯一的约束。【参考方案3】:
你的逻辑一开始就不正确
SELECT project_id FROM [projects] WHERE project_name = @Name
可能会返回多个结果。您可能已经进行了检查以确保只有一个项目具有同一个名称,但系统不知道这一点,您最终会在表中插入多条记录
解决方法可以是您将其更改为(只是为了使其工作)
INSERT INTO [project_manager] (project_id, manager_id) SELECT project_id, @ID FROM [projects] WHERE project_name = @Name
但是,不推荐。
您需要保存为项目名称生成的 id 并将它们传递给您的查询。
INSERT INTO [project_manager] (project_id, manager_id) VALUES (@ProjectID, @ID)
【讨论】:
您能解释一下“...但是系统不知道这一点,您最终会在表中插入多条记录”这个术语吗? 假设数据库中有2条项目名称为“Project ABC”的记录。然后您的语句将在 project_manager 表中插入 2 个条目。 不可能发生,因为第一个查询“SELECT COUNT(*) FROM [projects] WHERE project_name = @Name”将检查名称是否令人兴奋,对吗? 您可以放置多个检查以避免这种情况。但是,您需要以正确的方式进行操作。【参考方案4】:首先,您将整个逻辑转移到安全且易于维护的存储过程中。此外,在您的情况下,sqlserver 只有一次命中,而不是 3 次。
也可以使用 @@identity 或 SCOPE_IDENTITY() 来获取插入的项目 ID 的 ID。
所以像@Hamlet-Hakobyan 建议的那样制作一个 sp 和代码。试着让世界从复杂变得简单,而不是从简单变得复杂。
你的代码作为基本的东西很好理解,但不是在专业场景中。
【讨论】:
以上是关于SQL 服务器:使用 select 和其他参数插入的主要内容,如果未能解决你的问题,请参考以下文章
Pyodbc 未检测 SQL 语句中的参数标记(即 - 插入表 SELECT ...)到 Hive 表。这个问题有解决方法吗?