2017-01-25 5 views
3

Я новичок в Firebird DML.Как объявить/использовать локальные переменные в клиентских сценариях DML для Firebird

В TransactSQL я могу объявить и использовать переменные свободно и просто, как и в

declare @myID int 

select @myID = 42 

и использовать эти переменные в ЗЕЬЕСТЕ

select * from mytable where id = @myID 

и передавать значения между различными операторами.

Вопрос, просто, как я могу объявить и использовать локальные переменные в клиентском сценарии Firebird DML?

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

update mytable set price = 2 * price; 
select * from mytable; 

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

Googling around, я столкнулся с конструкцией EXECUTE BLOCK для PSql Firebird, которая, очевидно, поддерживает DECLARE VARIABLE, но она выглядит громоздкой, похоже, содержит некоторые странные ограничения, с которыми я никогда не сталкивался в TransactSQL, и, похоже, быть предназначенным для типа клиентских DML-скриптов, которые я пытаюсь сделать.

+0

Вам нужно будет использовать блок выполнения - вы можете передать параметры. – nater

+0

@nater: спасибо, но я предпочел бы вставлять иглы в глаза. блок исполнения кажется мерзостью для меня. –

+0

Вы уверены, что параметры не будут работать? Ваш пример не иллюстрирует это. –

ответ

2

Я боролся с этой проблемой в течение последних двух дней, чтобы попытаться закончить свой ответ на этот вопрос: sql and fifo simple select; мне потребовалось около получаса, чтобы написать и проверить способ TransactSQL делать то, что спросил ОП.

Я бы отправил маршрут EXECUTE BLOCK, который был предложен вам, но я продолжал сталкиваться с вещами DML, которые, по-видимому, им не разрешены, поэтому я отказался от этого политически корректным способом.

Итак, вместо этого я сделал это так, чтобы пуристы Firebird aghast: вместо того, чтобы пытаться объявить переменные, просто создайте временную таблицу, содержащую столбцы, соответствующие используемым переменным, и идентификатор, чтобы сделать его легким чтобы извлечь из него значения, а затем сохранить значения переменной в одной строке в нем. Что-то вроде:

create table variables(ID int, myID int, myStringVar charchar(80), [etc...]) 

Очевидно, что вы можете инициализировать эту таблицу, как вам нравится и обновить значения столбцов, как вы идете вперед. Доступ значения в ней немного более громоздкий, чем доступе значения переменного, но не намного, так как в

update mytable set somecolumn = 666 where id = (select myID from variables where ID = 1) 

Я уверен, что вы получите идею. Единственное незначительное раздражение, которое я обнаружил при этом, и tbh. Я не уверен, что это вещь Firebird или FlameRobin, так это то, что кажется необходимым обернуть создание объектов db, таких как таблицы и представления, в транзакции, которая происходит, прежде чем вы попытаетесь создать блок операторов, который их использует.

+0

Да, это был ваш ответ на тот вопрос, который заставлял меня задуматься об этом. В любом случае, спасибо, я могу перестать беспокоиться об этом сейчас. –

+0

У Firebird есть явные временные таблицы, содержимое которых зависит от транзакции или подключения. Что касается транзакций: DDL в Firebird является транзакционным: вам нужно указать границу транзакции самостоятельно (хотя некоторые инструменты имеют параметр «auto-commit DDL»), но объекты, созданные в транзакции, не могут использоваться в DML в этой же транзакции. –

+0

BTW: большое предложение использовать временные таблицы, в некоторых случаях вы также можете рассмотреть контекстные функции: https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-functions-scalarfuncs.html#fblangref25 -функции-workcontext –

1

Единственный способ иметь реальные переменные - как вы уже обнаружили, - использовать execute block (что для всех целей и задач является анонимной хранимой процедурой) или, конечно же, обычной хранимой процедурой.

Как указано в answer by MartynA, вы также можете использовать таблицу с переменными, хотя я бы предположил, что для этого используется global temporary table, поскольку это сохраняет «приватные» переменные для соединения или транзакции.

Еще один вариант (который я полностью забыл ранее) заключается в использовании переменных контекста с использованием rdb$get_context and rdb$set_context, хотя это может стать немного громоздким. Например, чтобы установить переменную x вы можете использовать:

select rdb$set_context('USER_SESSION', 'x', 5) from rdb$database; 

Возвращаемое значение это 0, если переменная была вновь создана и 1, если переменная уже существует. Значения преобразуются в VARCHAR(255), поэтому они должны быть типами, которые могут быть отлиты до VARCHAR(255). Вы можете удалить переменную, установив ее на NULL. Вместо USER_SESSION вы также можете использовать USER_TRANSACTION.

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

Получение переменной может быть сделано с

select rdb$get_context('USER_SESSION', 'x') from rdb$database; 

NULL который возвращает, если переменная не существует, или иным образом в VARCHAR(255) со значением.

 Смежные вопросы

  • Нет связанных вопросов^_^