MS SQL разбивает старую таблицу на отношение многие ко многим - PullRequest
0 голосов
/ 10 января 2019

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

В старой таблице нет столбца идентификаторов.

Старый стол:

CustomerNumber
FirstName
LastName
Address
Postal
City
....

Новые таблицы

Заказчик:

Id
Customernumber
Firstname
Lastname
... ect

Адрес:

Id
Address
Postal
City
... ect

CustomerAddress

Id
CustomerId
AddressId

Теперь, как я могу использовать старые табели в новые, используя SQL?

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

declare 
@CustomerId bigint,
@CustomerNumber float, 
@Status int,
@Address varchar(50),
@RoadNumber int,
@LastEdited datetime,

@AddressId bigint

declare my_cursor cursor
local static read_only forward_only
for
    select CustomerNumber, Address, Housenumber, Status, Date
    from [db1].dbo.OldCustomer k
    where 
        FIRMANR in (1, 40, 60, 80, 90, 120, 180, 400)

    open my_cursor
    fetch next from my_cursor into @CustomerNumber, @Address, @RoadNumber, @Status, @LastEdited
while @@FETCH_STATUS = 0
begin
    --if the customer already exists we get the identity
    if exists (select Id from [db2].dbo.Customers where CustomerNumber = @CustomerNumber)
        select @CustomerId = Id from [db2].dbo.Customers where CustomerNumber = @CustomerNumber

    --if the customer does not exit we need to insert and retrieve the new Identity value
    else
        begin
            -- insert the customer
            insert into [db2].dbo.Customers (CustomerNumber, [Status], LastEdited) values (@CustomerNumber, @Status, @LastEdited)
            set @CustomerId = SCOPE_IDENTITY()
        end

    -- get address if it already exists
    if exists (select Id from [db2].dbo.Addresses where Road = @Address and Roadnumber = @RoadNumber)
        select @AddressId = Id from [db2].dbo.Addresses where Road = @Address and Roadnumber = @RoadNumber
    else
        begin
            -- insert new addresses
            insert into [db2].dbo.Addresses (Road,Roadnumber) values (@Address, @RoadNumber)
            set @AddressId = SCOPE_IDENTITY()
        end

    -- insert customer => address reference if it does not exist
    if not exists (select Id from [db2].dbo.CustomerAddress where CustomerId = @CustomerId and AddressId = @AddressId)
        -- insert customer => address reference
        insert into [db2].dbo.CustomerAddress(CustomerId,AddressId) values (@CustomerId, @AddressId)


    fetch next from my_cursor into @CustomerNumber, @Address, @RoadNumber, @Status, @LastEdited
end

close my_cursor
deallocate my_cursor

1 Ответ

0 голосов
/ 10 января 2019

Вероятно, было бы проще всего:

  • Добавить столбец к старому клиенту с именем AddressId
  • Заполните его уникальными идентификаторами (вы можете повторно использовать идентификатор клиента или, если его GUID, использовать NewID ())
  • Создание новых таблиц для адреса и обычного адреса
  • Вставить часть старых данных о клиентах в каждую новую таблицу
  • Удалить столбцы от Клиента, которые относятся к адресу

--populate new Address table
INSERT INTO Address(id,col1,col2...)
SELECT AddressID, col1, col2... FROM Customer

--populate new CustomerAddress table
INSERT INTO CustomerAddress(CustomerId,AddressId)
SELECT Id, AddressID FROM Customer

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

Не указывайте CustomerAddress свой собственный столбец Id; первичным ключом CustomerAddress является комбинация CustomerId и AddressId; сделать композитный ПК, а не отдельный

Tbh, я бы, вероятно, не имел таблицы CustomerAddress, а вместо этого просто имел бы столбец BillingAddressId, WorkAddressId, HomeAddressId, ShippingAddressId в customer, но вам решать, как это сделать; Если у вас много и типы переменных адресов, то, конечно, у вас есть разбивка M: M, но если реально ваши клиенты будут иметь только до 3 адресов и т. Д., Я бы придерживался именованного столбца с указанием того, какой адрес был для клиента 1021 *

Если вы используете таблицу CustomerAddress, рассмотрите возможность добавления столбца с указанием типа / причины для адреса

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