Что такое T-SQL для нормализации существующей таблицы? - PullRequest
5 голосов
/ 11 февраля 2011

Я хотел бы преобразовать существующую таблицу в первую нормальную форму (простейшая возможная нормализация; см. Пример).

Вы случайно не знаете, что такое T-SQL для такого рода проблем??Большое спасибо!

enter image description here

Обновление

Попробовал ответ ниже, все заработало отлично.Вот шаги, которые я использовал для проверки ответа:

  1. Запустите Microsoft SQL Management Studio.
  2. Создайте таблицы со следующими данными.
  3. Убедитесь, чточто для идентификатора в «Заказчике» установлено значение «Первичный ключ» и «идентификатор».
  4. Убедитесь, что для идентификатора в «Заказе» нет специальных настроек (это внешний ключ).
  5. Откройте диаграмму базы данных, затем создайте отношения 1: * между таблицами «Заказчик» и «Заказ».
  6. Выполните сценарий для таблиц «Заказчик» и «Заказ», он будетавтоматически нормализует данные должным образом.
  7. Это очень полезно, если вы начинаете с плоского CSV-файла, который только что был импортирован, и хотите скопировать информацию в нормализованную форму в базе данных.

Ответы [ 4 ]

5 голосов
/ 11 февраля 2011

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

Сначала я вставлю данные в промежуточную таблицу и добавлю столбец для идентификатора, который будет нулевым. Затем я написал бы вставку в родительскую таблицу, используя предложение OUTPUT для вывода идентификаторов и естественного ключа в табличную переменную. Затем я бы использовал переменную таблицы для обновления поля id в промежуточной таблице. Затем я вставлял записи из промежуточной таблицы в другие таблицы. Поскольку у меня теперь есть идентификатор, больше нет необходимости обращаться к исходной родительской таблице. (Если количество записей велико, я мог бы также проиндексировать промежуточную таблицу).

Теперь, если у вас нет естественного ключа, процесс усложняется, потому что у вас нет способа определить, какая запись кому идет. Затем я обычно добавляю идентификатор в промежуточную таблицу, а затем выполняю первоначальный импорт в родительскую таблицу по одной записи за раз (включая stagingtableid в качестве переменной в курсоре), а затем обновляю промежуточную таблицу, используя каждый идентификатор родительской таблицы, как есть. создано. После обновления всех исходных записей я использую основанные на множестве процессы для вставки или обновления других таблиц.

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

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

Если это очень сложное преобразование, вы можете рассмотреть возможность использования служб SSIS.

4 голосов
/ 11 февраля 2011

Самое простое решение - написать запрос для импорта:

-- assuming that Id is an Identity column or has some default to generate keys.
Insert Customer( [Name] )
Select Name
From Flat_csv_file
Group By Name

Insert Order( [Customer], [Description], Cost )
Select C.Id, F.Description F.Cost
From Customer As C
    Join Flat_csv_file As F
        On F.Name = C.Name
4 голосов
/ 11 февраля 2011

Начиная с таблицы Customer

INSERT INTO Customer (Name)
SELECT DISTINCT Name
FROM Flat_CSV_File

Если вы повторили импорт

INSERT INTO Customer (Name)
SELECT DISTINCT f.Name
FROM Flat_CSV_File f
LEFT OUTER JOIN Customer c ON f.Name = c.Name
WHERE c.Id IS NULL

Orders (имя вашей таблицы Order - это зарезервированное слово в TSQL, поэтому вам нужно заключить его в кавычкис квадратными скобками)

INSERT INTO [Order] (CustomerId, Description, Cost)
SELECT c.Id, f.Description, f.Cost
FROM Flat_CSV_File f
INNER JOIN Customer c ON f.Name = c.Name
0 голосов
/ 11 февраля 2011

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

SET IDENTITY_INSERT Customers ON

INSERT Customers
(
   ...
)
SELECT
   ...
FROM
   openrowset(...)

SET IDENTITY_INSERT Customers ON



SET IDENTITY_INSERT Orders ON

INSERT Orders
(
   ...
)
SELECT
   ...
FROM
   openrowset(...)

SET IDENTITY_INSERT Orders ON

. Если вам нужно чисто TSQL-решение, я бы создал временные таблицы для выполнения той же основной задачи и вставил их из временных таблиц вместо .csv.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...