2009-08-25 3 views
2

У меня есть эта таблица, у которой нет первичного ключа.Создайте уникальный первичный ключ (хэш) из столбцов базы данных

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

Если бы это был язык программирования, как Java, я бы:

int hash = column1 * 31 + column2 * 31 + column3*31 

Или что-то подобное. Но это SQL.

Как создать первичный ключ из значений доступных столбцов? Мне не удастся просто пометить все столбцы как PK, так как мне нужно сравнить их с данными из другой таблицы DB.

В моем столе есть 3 номера и дата.

EDIT Что моя проблема

Я думаю, что немного больше фона необходимо. Прошу прощения за то, что не предоставил его раньше.

У меня есть база данных (dm), которая обновляется каждый день из другого db (исходного источника). Он имеет записи за последние два года.

В прошлом месяце (июль) процесс обновления был нарушен, и в течение месяца данные не обновлялись в дм.

Я вручную создаю таблицу с той же структурой в своем Oracle XE, и я копирую записи из исходного источника в свой db (myxe). Я скопировал только записи с июля, чтобы создать отчет, необходимый к концу месяца ,

Наконец, на август 8 процесс обновления был исправлен, и записи, которые ожидали переноса этого автоматического процесса, были скопированы в базу данных (от originalsource до dm).

Этот процесс очищает исходный источник данных после его копирования (в дм).

Все выглядят прекрасно, но мы просто понимаем, что количество записей заблудился (около 25% в июле)

Итак, что я хочу сделать, это использовать мое резервное копирование (myxe) и вставить в базе данных (дм) отсутствуют все эти записи.

Проблема здесь:

  • Они не имеют четко определенного ПК.
  • Они находятся в разных базах данных.

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

EDIT 2

Так что я сделал следующее в местной среде: (? .. союз)

select a.* from [email protected] a , the_table b where 
a.idle = b.idle and 
a.activity = b.activity and 
a.finishdate = b.finishdate 

который возвращает все строки, которые присутствуют в обеих базах данных Я получил 2000 записей.

Что я буду делать дальше, это удалить их все из целевой БД, а затем просто вставить их все с моего дб в целевую таблицу

Я надеюсь, что я не получаю в чем-то худшим: - S: -S

+1

'@ Oscar': имейте в виду, что ваш запрос« EDIT2 »не будет выбирать строки, которые имеют« NULL »в обоих столбцах в обеих таблицах. – Quassnoi

+0

Спасибо за совет ... – OscarRyz

ответ

3

Просто создать суррогатный ключ:

ALTER TABLE mytable ADD pk_col INT 

UPDATE mytable 
SET  pk_col = rownum 

ALTER TABLE mytable MODIFY pk_col INT NOT NULL 

ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col) 

или это:

ALTER TABLE mytable ADD pk_col RAW(16) 

UPDATE mytable 
SET  pk_col = SYS_GUID() 

ALTER TABLE mytable MODIFY pk_col RAW(16) NOT NULL 

ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col) 

Последний использует GUID «S, которые являются уникальными по всем базам данных, но потребляют больше пространства и гораздо медленнее, чтобы генерировать (ваши INSERT» s будет медленным)

Update:

Если вам нужно создать так же PRIMARY KEY с на двух таблиц с одинаковыми данных, использовать это:

MERGE 
INTO mytable v 
USING (
     SELECT rowid AS rid, rownum AS rn 
     FROM mytable 
     ORDER BY 
       co1l, col2, col3 
     ) 
ON  (v.rowid = rid) 
WHEN MATCHED THEN 
UPDATE 
SET  pk_col = rn 

Обратите внимание, что таблицы должны быть одинаковыми с точностью до одной строки (я. е. имеют одинаковое количество строк с одинаковыми данными в них).

Update 2:

Для самой вашей проблемы, вам не нужен PK вообще.

Если вы просто хотите, чтобы выбрать записи, отсутствующие в dm, используйте этот (на dm стороне)

SELECT * 
FROM [email protected] 
MINUS 
SELECT * 
FROM mytable 

Это вернет все записи, которые существуют в [email protected], но не в [email protected]

Обратите внимание, что он сжимает все дубликаты, если таковые имеются.

+0

Второй пример (с использованием GUID), не будет ли этот код устанавливать один и тот же идентификатор GUID для каждой записи? В Oracle GUID должен быть varchar2 (32), – Jay

+0

Будет ли какой-либо из этих буксиров создать одно и то же значение для двух строк с теми же данными в двух разных Базах данных? ?? – OscarRyz

+0

'@ Jay': ** a:) ** нет, это не будет, и ** b) ** нет, он не должен. В 'Oracle',' SYS_GUID() 'возвращает новое значение типа' RAW (16) 'для каждого вызова. – Quassnoi

3

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

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

1

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

Select Table2.SomeFields 
    FROM Table1 LEFT OUTER JOIN Table2 ON 
     (Table1.col1 * 31) + (Table1.col2 * 31) + (Table1.col3 * 31) + 
      ((DatePart(year,Table1.date) + DatePart(month,Table1.date) + DatePart(day,Table1.date))* 31) = Table2.hashedPk 

выше запрос будет работать на SQL Server, разница только для Oracle будет в плане того, как вы справляетесь преобразование даты.Кроме того, существуют другие функции для преобразования дат в SQL Server, поэтому это далеко не единственное решение.

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

1

Если вы загружаете новую таблицу со значениями из старой таблицы, а затем вам необходимо присоединиться к двум таблицам, вы можете только «правильно» сделать это, если сможете однозначно идентифицировать каждую строку в исходной таблице. Решение Quassnoi позволит вам сделать это, если вы можете сначала изменить старую таблицу, добавив новый столбец.

Если вы не можете изменить исходную таблицу, то будет генерироваться некоторая форма хеш-кода на основе столбцов старой таблицы, но опять же, только если хэш-коды однозначно идентифицируют каждую строку. (Oracle имеет функции контрольной суммы, верно? Если да, используйте их.)

Если уникальность кода хеш-кода не может быть гарантирована, вам может потребоваться установить первичный ключ, состоящий из как можно большего количества столбцов для обеспечения уникальности (например, естественного ключ). Если нет естественного ключа, ну, я слышал, как только Oracle предоставляет rownum для каждой строки данных, вы могли бы использовать это?

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