Как вставить записи в таблицу в цикле?

#arrays #sql-server #loops

#массивы #sql-сервер #циклы

Вопрос:

У меня есть таблица с полем идентификатора, не являющимся автоинкрементом. Мне нужно создать массив varchar, а затем вставить данные из массива в таблицу.

Проблема в том, что я не знаю, как объявить такой массив. А также я не знаю, как обращаться к значению по индексу в цикле.

 declare @newCodesList - ???
declare @counter int = 0
declare @lastID int = (select MAX(Id) from OrganizationCode)

while @counter < LEN(@newCodesList)
begin
    @lastID = @lastID   1

    insert into OrganizationCodeCopy values(@lastID, @newCodesList[@counter])

    @counter = @counter   1
end
  

В верхнем коде я пытаюсь вставить значения в цикл после нахождения идентификатора последней записи и объявления счетчика

Комментарии:

1. в приведенном выше коде я не вижу никакой необходимости в массиве. Зачем вам это нужно? Было бы полезно, если бы вы объяснили, чего вы пытаетесь достичь, может быть, есть лучшие методы для этого

2. Зачем использовать цикл? Используйте метод, основанный на множестве. Чего вы на самом деле пытались добиться здесь?

3. Мне нужен скрипт, который обновляет таблицу, заполняя ее новыми значениями. Я никогда не пытался вставлять много НОВЫХ значений, поэтому цикл — это первое, что пришло мне в голову) Основная идея в том, что вручную вводились только новые данные. Я имею в виду, что в прошлый раз я вставил 20 значений своими руками. @GuidoG

4. Выглядит как задание для STRING_SPLIT и / или объединение в таблице чисел (или прямое соединение @newCodesList , если это на самом деле параметр с табличным значением). Вы не хотите писать циклы в SQL, если можете этого избежать; вместо этого найдите способ переформулировать вашу проблему в терминах таблиц.

5. Для более общего обсуждения того, как обрабатывать массивы значений в SQL, см. Это и это .

Ответ №1:

Вы могли бы использовать табличную переменную для хранения кодов. Затем выполните INSERT ... SELECT из этой переменной. Чтобы получить идентификаторы, вы можете использовать row_number() свой максимальный идентификатор из другой таблицы.

 DECLARE @codes TABLE
               (code nvarchar(4));

INSERT INTO @codes
            (code)
            VALUES ('A01B'),
                   ('B03C'),
                   ('X97K');

INSERT INTO organizationcodecopy
            (id,
             code)
            SELECT (SELECT coalesce(max(id), 0)
                           FROM organizationcode)   row_number() OVER (ORDER BY code) id,
                   code
                   FROM @codes;
  

db<>скрипка

Ответ №2:

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

 DECLARE @newCodesList VARCHAR(MAX) = 'value1,value2'
DECLARE @lastID int = (SELECT MAX(Id) FROM OrganizationCode)

INSERT INTO OrganizationCodeCopy 
(
    Id, 
    Code
)
SELECT 
    @lastID   ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id
    Element AS Code
FROM 
    asi_SplitString(@newCodesList, ',')
  

Комментарии:

1. Откуда asi_SplitString берется?

2. @ThomasSchremser Извините, я забыл упомянуть, что функция доступна не во всех итерациях SQL server. Тем не менее, вы можете найти сценарий функции здесь: docs.imis.com/15.2/Schema/Programmability/Functions /…

Ответ №3:

Использование циклов не является хорошим решением. Вы можете попытаться определить временную таблицу и вставить новые данные одним оператором. Значения для Id генерируются с ROW_NUMBER() помощью функции:

 -- New data
CREATE TABLE #NewCodes (
    Code varchar(50)
)
INSERT INTO #NewCodes
    (Code)
VALUES
    ('Code1'),
    ('Code2'),
    ('Code3'),
    ('Code4'),
    ('Code5'),
    ('Code6')

-- Last ID
DECLARE @LastID int
SELECT @LastId = (SELECT ISNULL(MAX(Id), 0) FROM OrganizationCode)

-- Statement
INSERT INTO OrganizationCode
    (Id, Code)
SELECT
    @LastId   ROW_NUMBER() OVER (ORDER BY Code) AS Id,
    [Code]
FROM #NewCodes