Вставьте данные дважды в одну таблицу с помощью курсора - PullRequest
0 голосов
/ 12 мая 2018

У меня есть две таблицы cursor_created и cursor_copied с одинаковыми столбцами. Я хочу получить данные из cursor_created и вставить их в cursor_copied дважды, используя цикл.

Запрос:

DECLARE @ID INT
DECLARE @Name NVARCHAR(50)
DECLARE @Amount DECIMAL(18,0)
DECLARE @Date NVARCHAR(50)

DECLARE IDs CURSOR FOR 
    SELECT
        ID, Name, Amount, Date 
    FROM
        cursor_created 

OPEN IDs

FETCH NEXT FROM IDs into @ID, @Name, @Amount, @Date

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO cursor_copied (id, name, amount, date)
    VALUES (@ID, @Name, @Amount, @Date)
    ----Verify that Data in TestTable
    --print @ID 
    --print @Name
    --print @Amount
    --print @Date

    --SELECT @ID, @Name, @Amount, @Date FROM cursor_copied 
    FETCH NEXT FROM IDs into @ID, @Name, @Amount, @Date
END

CLOSE IDs
DEALLOCATE IDs

Выход:

ID  Name  Amount  Date
------------------------------------------
1   A     2000    2008-03-15 18:15:43.000
2   B     3000    2008-03-15 18:15:43.000
3   C     4000    2008-03-15 18:15:43.000

Я хотел бы вместо этого:

ID  Name  Amount  Date
------------------------------------------
 1  A     2000    2008-03-15 18:15:43.000
 2  B     3000    2008-03-15 18:15:43.000
 3  C     4000    2008-03-15 18:15:43.000
 1  A     2000    2008-03-15 18:15:43.000
 2  B     3000    2008-03-15 18:15:43.000
 3  C     4000    2008-03-15 18:15:43.000

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

Использование курсора для этого является ошибкой. Вы должны использовать операции над множествами, где вы можете:

INSERT INTO cursor_copied (id, name, amount, date)
    SELECT ID, Name, Amount, Date 
    FROM cursor_created CROSS APPLY
         (VALUES (1), (2)) copies(n);

Даже если вы изучаете курсоры, очень важно узнать, когда они уместны. И они почти никогда не подходят, когда код можно заменить одним запросом.

0 голосов
/ 17 июня 2019

Вы можете просто переписать вашу вставку, как показано ниже внутри курсора:

INSERT INTO cursor_copied (id, name, amount, date)
    VALUES (@ID, @Name, @Amount, @Date),
           (@ID, @Name, @Amount, @Date)

НО выбранное вами решение может быть не лучшим решением для такого рода проблем.Если вас интересуют другие решения, пожалуйста, прочитайте также следующие истории.

Решение 1

см. @ GordonLinoff's ответ

Решение 2

Давайте рассмотрим проблему шаг за шагом:

Сначала предположим, что есть две таблицы, подобные этой:

CREATE TABLE t1(Id INT, Name NVARCHAR(50), Amount DECIMAL(18,0), Date NVARCHAR(50))
GO
CREATE TABLE t1_copy(Id INT, Name NVARCHAR(50), Amount DECIMAL(18,0), Date NVARCHAR(50))

Затем я полагаю, что я вставил следующие записи в t1:

INSERT INTO t1 VALUES
(1,'A', 2000,'2008-03-15 18:15:43.000'),
(2,'B', 3000,'2008-03-15 18:15:43.000'),
(3,'C', 4000,'2008-03-15 18:15:43.000')

Далее мне нужно подумать о запросе, который поможет мне создать дублированные записи.У меня есть множество доступных опций, таких как Cross Apply, как упоминал @GordonLinoff.Другой способ - использовать UNION ALL следующим образом:

SELECT t1.Id,
       t1.Name,
       t1.Amount,
       t1.Date FROM dbo.t1
UNION ALL
SELECT Id,
       Name,
       Amount,
       Date FROM dbo.t1;

Этот запрос даст желаемый результат, и мне нужно просто вставить их в таблицу назначения следующим образом:

INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
SELECT t1.Id,
       t1.Name,
       t1.Amount,
       t1.Date FROM dbo.t1
UNION ALL
SELECT Id,
       Name,
       Amount,
       Date FROM dbo.t1;

Очевидно, что перед вставкой в ​​таблицу может потребоваться обратить внимание на столбец Primary Key или Identity, если он существует!

Решение 3

Вы можете использовать GO!вот так:

   INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
   SELECT Id,Name,Amount,Date FROM dbo.t1
   GO 2

Это не то, что я бы порекомендовал, потому что GO - это пакетный сепаратор, и он доставит вам неприятности.Также вышеупомянутый запрос будет выполнен как две отдельные транзакции, что снова может стать проблемой!

Решение 4

Вы можете использовать оператор OUTPUT.однако из-за сложности, опять же, я не рекомендую это.Например:

   INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
   SELECT * FROM(
       INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
          OUTPUT Inserted.id, Inserted.Name, Inserted.Amount, Inserted.Date
       SELECT Id,Name,Amount,Date FROM dbo.t1) AS k

Как насчет использования курсора?

@ GordonLinoff упомянул точку ошибки использования курсора в этом сценарии, однако еслиВы настаиваете на использовании курсора, вам нужно объявить курсор в режиме Fast_Forward.Объявление его в режиме SCROLL не поможет вам и снизит общую производительность запроса!

DECLARE IDs CURSOR FAST_FORWARD FOR ...

Сравнение производительности:

Если мы просто посмотрим на план выполнения вышеупомянутых решений, мы увидим, что Решение 1 имеет лучший выход производительностипо сравнению с другим решением.На моем ПК вывод плана выполнения выглядит следующим образом:

Solution 1 ====================> Subtree Cost: 0.0133
Solution 2 ====================> Subtree Cost: 0.0165
Solution 3 ====================> Subtree Cost: 0.0132*2=0.0264
Solution 4 ====================> Subtree Cost: 0.0232
Cursor in SCROLL mode =========> Subtree Cost: 0.0332
Cursor in Fast_Forward mode ===> Subtree Cost: 0.0203

Эти цифры могут отличаться на вашем ПК!

0 голосов
/ 12 мая 2018

вы должны использовать after insert триггер.

вы можете установить on after insert триггер для cursor_inserted таблицы и управлять событием вставки в эту таблицу, а затем вставлять дублирующую строку.

CREATE TRIGGER DublicateInsert ON cursor_copied 
AFTER INSERT  
AS
BEGIN
INSERT INTO cursor_copied (id, name, amount, date)
    SELECT id, name, amount, date
    FROM  INSERTED 
END

или вы можете использовать этот синтаксис для ваших проблем

INSERT INTO cursor_copied (id, name, amount, date)
OUTPUT inserted.id, inserted.name,inserted.amount,inserted.date
INTO cursor_copied (id, name, amount, date)
 VALUES (@ID, @Name, @Amount, @Date)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...