Обновите столбцы в DB2, используя произвольно выбранные статические значения, предоставленные во время выполнения - PullRequest
0 голосов
/ 02 мая 2018

Я хотел бы обновить строки со значениями, выбранными случайным образом из набора возможных значений.

В идеале я мог бы предоставить эти значения во время выполнения, используя JdbcTemplate из приложения Java.

Пример: В таблице столбец «имя» может содержать любое имя. Цель состоит в том, чтобы пробежаться по таблице и изменить все имена на «Боб» или «Алиса».

Я знаю, что это можно сделать, создав функцию sql. Я проверил это, и это было нормально, но мне интересно, можно ли просто использовать простой запрос?

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

UPDATE test.table
SET first_name = 
    (SELECT a.name 
     FROM 
         (SELECT a.name, RAND() idx 
          FROM (VALUES('Alice'), ('Bob')) AS a(name) ORDER BY idx FETCH FIRST 1 ROW ONLY) as a)
;

Я пытался использовать MERGE INTO, но он даже не запустился (возможные имена не найдены в запросе SET). Мне еще предстоит выяснить, почему:

MERGE INTO test.table
    USING
        (SELECT
            names.fname 
        FROM 
            (VALUES('Alice'), ('Bob'), ('Rob')) AS names(fname)) AS possible_names
    ON ( test.table.first_name IS NOT NULL )
    WHEN MATCHED THEN 
        UPDATE SET
        -- select random name
        first_name = (SELECT fname FROM possible_names ORDER BY idx FETCH FIRST 1 ROW ONLY)
; 

РЕДАКТИРОВАТЬ: Если возможно, я бы хотел сосредоточиться только на обновлении полей и не зависеть от знания первичных ключей и тому подобное.

Ответы [ 2 ]

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

Если ваша таблица имеет первичный ключ, это будет работать. Я предположил, что PK это столбец id.

UPDATE test.table t
SET first_name = 
( SELECT name from
    ( SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY R) AS RN FROM 
        ( SELECT *, RAND() R
          FROM test.table, TABLE(VALUES('Alice'), ('Bob')) AS d(name)  
         )
     )
 AS u
WHERE t.id = u.id and rn = 1
)
;

Возможно, есть более приятное / более эффективное решение, но я оставлю это другим.

К вашему сведению Я использовал следующие DDL и данные для проверки вышеупомянутого.

create table test.table(id int not null primary key, first_name varchar(32));
insert into test.table values (1,'Flo'),(2,'Fred'),(3,'Sue'),(4,'John'),(5,'Jim');
0 голосов
/ 02 мая 2018

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

Для принудительного выполнения выборки для каждой строки необходимо как-то соотнести ее с обновляемой таблицей, например:

UPDATE test.table
SET first_name = 
    (SELECT a.name 
     FROM (VALUES('Alice'), ('Bob')) AS a(name) 
     ORDER BY RAND(ASCII(SUBSTR(first_name, 1, 1))) 
     FETCH FIRST 1 ROW ONLY)

или может быть даже

UPDATE test.table
SET first_name = 
    (SELECT a.name 
     FROM (VALUES('Alice'), ('Bob')) AS a(name) 
     ORDER BY first_name, RAND() 
     FETCH FIRST 1 ROW ONLY)

Теперь, когда результат подвыбора, по-видимому, зависит от значения соответствующей строки в целевой таблице, нет другого выбора, кроме как выполнить его для каждой строки.

...