Как передать массив в инструкцию update?

#sql #postgresql #groovy #jira

#sql #postgresql #groovy #jira

Вопрос:

Я хотел бы выполнить обновление для переменного количества строк. Я попробовал следующее, но это не работает.

 def sernos = issue.getCustomFieldValue (ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10719))
def update = '''update mytable set status = 'reserved' where id in (${sernos})'''
sql.executeUpdate (update)
  

Я получаю сообщение об ошибке от Postgresql:

синтаксическая ошибка в $

Мне кажется, что Groovy не расширяет GString . sernos это ArrayList строк. Следующий код:

 log.warn (sernos.getClass())
log.warn (sernos[0].getClass())
  

Отчеты:

 2020-10-15 12:09:06,926 WARN [runner.ScriptBindingsManager]: class java.util.ArrayList
2020-10-15 12:09:06,926 WARN [runner.ScriptBindingsManager]: class java.lang.String
  

Я также пробовал это:

 def update = '''update mytable set status = 'reserved' where id in (${Sql.expand(sernos)})'''
  

Но это тоже не работает.

Как передать список строк в where условие SQL?

Ответ №1:

То, что вы отправляете, приведет к получению запроса с недопустимым синтаксисом SQL, что-то вроде

 update mytable set status = 'reserved' where id in ([a, b, c, d])
  

Где [a, b, c, d] toString() результат списка. Вам нужно преобразовать это в текст, подходящий для IN предложения:

 def inText = sernos.collect{"'$it'"}.join(', ')

//also, you need double quotes (" or """) for GString interpolation
def update = "update mytable set status = 'reserved' where id in ($inText)"
...
  

Для этого будет установлено update значение, подобное

 update mytable set status = 'reserved' where id in ('a', 'b', 'c', 'd')
  

Теперь вам нужно быть осторожным с содержимым sernos , потому что приведенное выше все равно приведет к недопустимому синтаксису SQL, если текст в списке содержит одинарные кавычки. Вам придется избегать их, если это ожидается.

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

1. Но это создает SQL путем конкатенации строк и открывает дверь для SQL-инъекций.

2. @ceving похоже, вы все равно используете динамические параметры. Если sernos он исходит от ваших пользователей, то, конечно, вам следует опасаться делать что-либо подобное для начала.

Ответ №2:

Это решило мою проблему:

 def sernos = issue.getCustomFieldValue (ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10719))
def questionmarks = sernos.collect {'?'}.join (',')
def update = """update mytable set status = 'reserved' where id in (${questionmarks})"""
sql.executeUpdate (update.toString(), sernos)