Как удалить таблицу firebird в процедуре
Предложение ADD CONSTRAINT может быть использовано для добавления ограничений на уровне таблицы для нового или существующего столбца.
ALTER TABLE имя ADD [CONSTRAINT ограничение] <ограничение-таблицы>;
где ограничение-таблицы- может быть ограничением PRIMARY KEY, FOREIGN KEY, UNIQUE или CHECK. Фраза CONSTRAINT ограничение может быть опущена, если вам не нужно имя ограничения.
Для добавления ограничения UNIQUE в таблицу EMPLOYEE вы можете использовать следующий оператор:
ALTER TABLE EMPLOYEE
ADD CONSTRAINT UQ_PHONE_EXT UNIQUE(PHONE_EXT);
Когда недостаточно ALTER TABLE
Иногда бывает нужным произвести изменение столбца, которое нельзя совершить с помощью ALTER TABLE. Примером может быть случай, когда столбец, хранящий международные элементы языка, имеет набор символов NONE, который нужно заменить на другой набор символов, чтобы исправить ошибку проектирования, или телефонный номер, определенный вначале кем-то как целое, нужно заменить на 18-символьный столбец.
В первом случае невозможно изменить набор символов для столбца, следовательно, вам нужно средство, чтобы сохранить данные и сделать их доступными в правильном наборе символов. Во втором случае простое изменение типа данных столбца с телефонным номером не будет работать, если у нас уже существуют целые числа в этом столбце. Мы хотим сохранить существующие числа, но нам нужно преобразовать их в строки. Это не может быть выполнено в существующей структуре, потому что столбец с целым типом данных не может хранить строки.
Прием заключается в создании в таблице временного столбца с правильными атрибутами и переносе туда данных, после чего вы удалите и пересоздадите нужный столбец.
1. Добавьте в таблицу временный столбец с теми атрибутами, которые вам нужны.
ALTER TABLE PERSONNEL
ADD TEMP_COL VARCHAR (18) ;
2. Скопируйте данные из столбца, который вы будете изменять, во временный столбец, преобразовывая их соответствующим образом (например, изменяя набор символов для конвертирования текстовых данных в правильный набор символов или, как в нашем примере, выполняя преобразование).
SET TEMP_COL = CAST(TEL_NUMBER AS VARCHAR(18))
WHERE TEL_NUMBER IS NOT NULL;
3. После проверки того, что данные во временном столбце были изменены, как планировалось, удалите старый столбец.
ALTER TABLE PERSONNEL DROP TEL_NUMBER;
4. Создайте «новый» столбец, с тем же именем, как и тот, который вы только что удалили, и с теми же атрибутами, что и у временного столбца.
ALTER TABLE PERSONNEL
ADD TEL_NUMBER VARCHAR (18);
5. Скопируйте данные во вновь созданный столбец.
SET TEL_NOMBER = TEMP_COL WHERE TEMP_COL IS NOT NULL;
6. После проверки того, что данные во вновь созданном столбце правильные, удалите временный столбец. Если хотите, вы можете также переместить пересозданный столбец на его старую позицию.
Сохраненная процедура пакетного удаления в Firebird
Мне нужно удалить кучу записей (буквально миллионы), но я не хочу делать это в отдельном заявлении из-за проблем с производительностью. Итак, я создал представление:
После этого делаю кучу удалений, например:
Я хочу импортировать эту логику в While loop и в хранимую процедуру. Я пробовал запрос SELECT COUNT вот так:
Могу ли я использовать этот номер в той же процедуре, что и условие, и как с этим справиться?
Я пробовал это и получаю сообщение об ошибке
ОШИБКА: ошибка динамического SQL; Код ошибки SQL = -104; Токен неизвестен; ПОКА
Я просто не могу осмыслить это.
Чтобы уточнить, в моем предыдущем вопросе я хотел знаю, как управлять garbage_collection после множества удаленных записей, и я сделал то, что было предложено — SELECT * FROM TABLE; или gfix -sweep , и это сработало очень хорошо.
После этого мне была передана еще одна база данных еще большего размера — более 50 миллионов. И проблема заключалась в том, что БД работала очень медленно. И мне удалось убить сервер, на котором он находился, с помощью оператора DELETE для очистки базы данных.
Вот почему я хотел попробовать удалять партиями. Проблема с торможением была чисто аппаратная — HDD пропал, и мы его заменили. После этого не было проблем с выполнением операторов и резервным копированием и восстановлением для освобождения дискового пространства.
3 ответа
из-за проблем с производительностью
Что это именно? Я не думаю, что вы действительно улучшаете производительность, просто выполняя delete в циклах, но в рамках одной транзакции или даже в разных TX, но в один и тот же промежуток времени. Кажется, вы решаете какую-то неправильную проблему. Проблема не в том, как вы создаете «мусор», а в том, как и когда Firebird «собирает» его.
Например, Select Count(*) в движках Interbase / Firebird означает естественное сканирование всей таблицы, и он часто запускает сборку мусора , которая сама по себе может затянуться, если было создано много мусора (и массовое удаление, безусловно, работает, независимо от того, выполняется ли это одним оператором из миллиона строк или миллионом операторов из одной строки).
Если вы действительно хотите замедлить удаление — вы должны распространять эту активность круглосуточно и сделать так, чтобы ваше клиентское приложение вызывало удаление SP, например, каждые 15 минут. Вам нужно будет добавить какой-нибудь столбец в таблицу, пометив, что он помечен для удаления, а затем выполнить такую работу
. и каждые 15 минут вы делаете EXECUTE PROCEDURE DeleteBatch(1000) .
В целом это, вероятно, будет только медленнее из-за однорядного «точного нацеливания» — но, по крайней мере, это приведет к увеличению задержек.
Но, как я уже сказал в ответе на предыдущий вопрос, лучше потратить время на изучение источника замедления, а не на обходное решение путем удаления данных.
При условии, что данные, которые вам нужно удалить, никогда не требуют отката после запуска хранимой процедуры, есть другой способ обработки массивных DELETE в хранимой процедуре.
Пример хранимой процедуры будет удалять по 500 000 строк за раз. Он будет повторяться до тех пор, пока не останется больше строк для удаления. АВТОНОМНАЯ ТРАНЗАКЦИЯ позволит вам поместить каждый оператор удаления в отдельную транзакцию, и он будет зафиксирован сразу после завершения оператора. Это вызывает неявную фиксацию внутри хранимой процедуры, чего вы обычно не можете сделать.
Firebird с драйвером .net — удалить таблицу, если существует
Я новичок в Firebird, и я тестирую несколько вещей, чтобы проверить различия между Fb и SQlite (и драйвером .net).
Я пытаюсь создать таблицу сброса, если она существует, с последующим созданием таблицы. В Sqlite я могу это сделать:
Однако в Firebird тот же запрос не работает. Я читал, что использовать IF непосредственно в Firebird SQL невозможно, поэтому я попытался использовать:
Но это также не удается со следующей ошибкой:
Dynamic SQL Error SQL error code = -104 Token unknown — line 1, column 27
Не могли бы вы мне помочь? Я пытался найти в Интернете дополнительную информацию, которая могла бы мне помочь, но безуспешно.



Ответы 1
В синтаксисе SQL Firebird нет drop table if exists , вместо этого используется recreate table . recreate table попытается удалить таблицу, если она существует, перед ее созданием. Синтаксис recreate table — кроме recreate вместо create — такой же, как create table .
Ваша попытка использовать execute block не удалась по двум причинам:
- Вы не можете выполнять два оператора вместе как команду. Если вы хотите выполнить сценарий из нескольких операторов, вам нужно будет выполнить каждый оператор отдельно или использовать класс FbScript , который проанализирует сценарий и выполнит отдельные операторы за вас.
- Даже если вы выполните эти операторы по отдельности, это все равно не удастся, потому что PSQL (язык хранимых процедур, используемый в execute block ) не позволяет выполнять DDL. Вы можете использовать execute statement , чтобы обойти это ограничение, но лучше этого не делать. Таким образом, вы также можете обратиться к предыдущему пункту, выполнив оба — с помощью execute statement — в execute block .
В качестве альтернативы вы можете просто отбросить таблицу безоговорочно и перехватить (и проигнорировать) полученное исключение.