#oracle
Вопрос:
У меня есть простая таблица Oracle, в которой уже есть данные:
CRATE NUMBER(10) 2V5 FLOAT(126) tstamp TIMESTAMP(6)¨
Я пытаюсь преобразовать его в это, включая данные внутри:
CRATE NUMBER(10) 2V5 FLOAT(126) tstamp TIMESTAMP(6) WITH TIME ZONE
Мне удалось сделать это с помощью следующего набора команд:
ALTER TABLE "TIMESTAMP_DEBUG_TABLE" ADD( "temp_ts" TIMESTAMP WITH TIME ZONE ); UPDATE "TIMESTAMP_DEBUG_TABLE" SET "temp_ts" = "tstamp" AT TIME ZONE 'Europe/Zurich'; ALTER TABLE "TIMESTAMP_DEBUG_TABLE" DROP COLUMN "tstamp"; ALTER TABLE "TIMESTAMP_DEBUG_TABLE" RENAME COLUMN "temp_ts" TO "tstamp";
Однако есть одна проблема. Каждый столбец имеет идентификатор столбца в oracle, который получается путем выполнения: SELECT column_id FROM USER_TAB_COLUMNS WHERE table_name = 'A' AND column_name = 'B';
Я использую этот идентификатор столбца в своем программном обеспечении, и на самом деле в моей базе данных есть еще одна таблица, которая рассматривает его как своего рода внешний ключ. При выполнении вышеуказанного набора команд идентификаторы столбцов перемешиваются, и целостность ссылок нарушается.
Как я могу решить эту проблему?
- Есть ли какой-либо способ повторно ввести этот столбец, не перетасовывая идентификаторы столбцов таблицы?
- Есть ли способ формализовать взаимосвязь идентификатора столбца? Могу ли я добавить ограничение FK в свою таблицу, которое указывает на идентификаторы столбцов других таблиц? Тогда я мог бы каскадировать.
- Какие-нибудь другие идеи/обходные пути?
Комментарии:
1. Oracle использует эту информацию для своих нужд. Вам не следует полагаться на это: у вас будет точно такое же отношение (таблица), если вы объявите cols в другом порядке. Вы даже можете заменить таблицу представлением, в котором столбцы проецируются в другом порядке: модель данных останется прежней с точки зрения потребления (и это основная причина, по которой мы используем базу данных, а не потому, что создавать таблицы слишком круто). Итак, вы использовали внутреннюю информацию БД как часть своей модели, и у вас возникли некоторые проблемы: пришло время погасить этот долг. Столбец адреса по его названию:
lt;schemagt;.lt;objectgt;.lt;columngt;
Ответ №1:
Полагаться на column_id
это в первую очередь кажется немного проблематичным. Казалось бы, имеет больше смысла полагаться на имя столбца, поскольку именно его эффективно использует в качестве ключа любая другая инструкция SQL в мире. Но я предполагаю, что изменение этого не является стартовым.
Это дороже с точки зрения ввода-вывода и времени, но вы можете создать новую таблицу, переместить данные, а затем переименовать ее. Это должно привести к конечному состоянию, в котором две таблицы имеют одинаковые column_id
значения (при условии, что timestamp_debug_table
в настоящее время ранее не было добавлено или удалено никаких столбцов, которые могли бы привести column_id
к неправильному порядку значений).
create table timestamp_debug_table2 ( crate number(10), "2V5" float(126), "tstamp" timestamp(6) with time zone ); insert into timestamp_debug_table2 select crate, "2V5", "tstamp" at time zone 'Europe/Zurich' from timestamp_debug_table; drop table timestamp_debug_table; alter table timestamp_debug_table2 rename to timestamp_debug_table;
Предполагая, что вы находитесь на 12c или более поздней версии, вы также можете сделать столбец невидимым и снова видимым, прежде чем удалить его, что также изменит column_id
значения. Это еще одна причина не зависеть от чего-то подобного column_id
, потому что Oracle может свободно возиться с ним, чтобы реализовать другие функциональные возможности. Никто, вероятно, не догадается, что выполнение чего-то вроде повторного создания невидимого и видимого столбца приведет к тому, что ваше программное обеспечение перестанет работать правильно.
ALTER TABLE "TIMESTAMP_DEBUG_TABLE" ADD( "temp_ts" TIMESTAMP WITH TIME ZONE ); UPDATE "TIMESTAMP_DEBUG_TABLE" SET "temp_ts" = "tstamp" AT TIME ZONE 'Europe/Zurich'; -- This causes the column_id in user_tab_columns to be set to NULL and "temp_ts" -- will have a value of 3 alter table TIMESTAMP_DEBUG_TABLE column "tstamp" invisible; -- Now the column_id in user_tab_columns will be 4 for "tstamp". "temp_ts" will -- still have a value of 3 alter table TIMESTAMP_DEBUG_TABLE column "tstamp" visible; ALTER TABLE "TIMESTAMP_DEBUG_TABLE" DROP COLUMN "tstamp"; ALTER TABLE "TIMESTAMP_DEBUG_TABLE" RENAME COLUMN "temp_ts" TO "tstamp";