【问题标题】:Loop in stored procedure of SQL ServerSQL Server 存储过程中的循环
【发布时间】:2019-11-11 07:55:24
【问题描述】:

我有一个这样的存储过程:

ALTER PROCEDURE [dbo].[insert_sms] 
    (@msg VARCHAR(MAX), @nodeid INT)    
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
    VALUES ((SELECT Mobile FROM NodesMobileSMS WHERE NodeID = @nodeid), @msg);
END

如何编写循环脚本,让(select Mobile from NodesMobileSMS) 中的每个手机号码执行插入查询?

编辑

select Mobile 
from NodesMobileSMS 
where NodeID = @nodeid

将返回“1;2;3;4;5”(每个选择查询的动态值),我想为“1;2;3;4;5”中的每个数字编写一个循环,它会在ManAlarm 中插入一行:

INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
VALUES (1, @msg);
INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
VALUES (2, @msg);
...
INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
VALUES (5, @msg);

像这样插入:

INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
VALUES ('1;2;3;4;5', @msg);

编辑2: 我写了一个函数 splitString 并插入查询:

INSERT INTO dbo.ManAlarm ([Mobile], [Content]) 
SELECT *,'message' from dbo.splitString('1;2;3;4;5',';');

成功了!谢谢大家!

【问题讨论】:

  • 不要在 SQL 中使用循环,该语言已准备好处理每个操作的行集。循环和游标很慢,通常是不好的做法,但有一些例外。您可以搜索术语 RBAR 以了解更多信息。
  • 请记住,如果您打算插入 100000 条记录,这不是一种有效的方法。
  • 不,最多只插入 20 行记录
  • 请发布您的数据集和您希望的结果集
  • 亲,您的查询结果是 1;2;3;4;5(这些值只有一行),所以您想拆分这些值并放入您的表中?

标签: sql-server stored-procedures sql-server-2008-r2


【解决方案1】:

你可以这样写:

INSERT INTO dbo.ManAlarm([Mobile], [Content]) 
SELECT Mobile, @msg from NodesMobileSMS where NodeID = @nodeid

在上面的查询中,我只是删除了 VALUES 关键字,因此您将 SELECT 的输出放入您的 ManAlarm 表中

但是如果你想写一个循环,你可以在NodesMobileSMS 上使用CURSOR,但这不是一个关于性能的好选择。

编辑(在 Kid1412 评论之后)

如果您想在ManAlarm 中写入与NodesMobileSMS 中存在但具有相同值的相同行,您必须编写如下:

INSERT INTO dbo.ManAlarm([Mobile], [Content]) 
SELECT 1, @msg from NodesMobileSMS where NodeID = @nodeid

如果您想添加任意数量的行,您可以将您的 INSERT 放入 FOR 循环中

编辑(在 Kid1412 说他使用 Sql Server 2016 之后)

INSERT INTO dbo.ManAlarm([Mobile], [Content]) 
SELECT STRING_SPLIT(Mobile, ';'), @msg from NodesMobileSMS where NodeID = @nodeid

【讨论】:

  • 如果那样,它将插入 Mobile 是一个与 "1;2;3;4;5" 相同的字符串数组,但我想插入相同的:INSERT INTO dbo.ManAlarm([Mobile], [内容]) 值(1,@msg);插入 dbo.ManAlarm([Mobile], [Content]) VALUES(2,@msg); ...
  • @Kid1412:在您的问题中,您已将选择作为来源。如果要添加与选择结果相同的基数,可以使用 1 而不是 Mobile 值重写查询。
  • 但是(SELECT Mobile from NodesMobileSMS)会返回动态值,所以不能重写查询
  • @Kid1412:请发布您的数据集和您希望的结果集,以便我可以更好地帮助您
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
相关资源
最近更新 更多