Мне была задана задача использовать курсор для дублирования таблиц. Скажем, теперь у меня есть 3 таблицы для дублирования: Компания, Person_Link & Лицо. Это отношения «от одного до многих», поскольку одна компания может иметь несколько человек.SQL Server - дубликаты нескольких таблиц с курсорами
Это мой код:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DuplicateCompanyInfo]
@Comp_CompanyId NVARCHAR(80)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @CompanyID NVARCHAR(30),
@PersonID NVARCHAR(30),
@PersonLinkID NVARCHAR(30),
@AddressLinkID NVARCHAR(30),
@AddressID NVARCHAR(30),
@PhoneLinkID NVARCHAR(30),
@PhoneID NVARCHAR(30)
EXEC @companyId = crm_next_id 5
EXEC @PersonId = crm_next_id 13
EXEC @PersonLinkId = crm_next_id 31
EXEC @AddressLinkId = crm_next_id 21
EXEC @AddressId = crm_next_id 1
EXEC @PhoneLinkId = crm_next_id 10208
EXEC @PhoneId = crm_next_id 14
-- Add Company
INSERT INTO Company
(
Comp_CompanyId, Comp_PrimaryPersonId, Comp_PrimaryAddressId, Comp_Name, Comp_Type, Comp_Status, Comp_CreatedBy,
Comp_CreatedDate, Comp_UpdatedBy, Comp_UpdatedDate, Comp_TimeStamp, Comp_SecTerr, Comp_WebSite
)
SELECT @companyId, @PersonId, @AddressId, Comp_Name, Comp_Type, Comp_Status, Comp_CreatedBy,
Comp_CreatedDate, '1', GETDATE(), Comp_TimeStamp, Comp_SecTerr, Comp_WebSite
FROM Company
WHERE Comp_CompanyId = @comp_companyid
------- PersonLink Cursor ---------------------------------------------
-- Declare Variables
DECLARE @c_PeLi_PersonLinkId NVARCHAR(30)
DECLARE @c_PeLi_PersonId NVARCHAR(30)
DECLARE @c_PeLi_CompanyID NVARCHAR(30)
DECLARE @c_PeLi_CreatedBy NVARCHAR(30)
DECLARE @c_PeLi_CreatedDate NVARCHAR(30)
DECLARE @c_PeLi_UpdatedBy NVARCHAR(30)
DECLARE @c_PeLi_UpdatedDate NVARCHAR(30)
DECLARE @c_PeLi_TimeStamp NVARCHAR(30)
--Declare Cursor
DECLARE @getPeLiID CURSOR
SET @getPeLiID= CURSOR FOR
SELECT PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy,
PeLi_UpdatedDate, PeLi_TimeStamp
FROM Person_Link
INNER JOIN Person
ON PeLi_PersonId = Pers_PersonId
AND PeLi_CompanyID = @comp_companyid
--Open Cursor & fetch 1st row into variables
OPEN @getPeLiID
FETCH NEXT FROM @getPeLiID INTO @c_PeLi_PersonLinkId, @c_PeLi_PersonId, @c_PeLi_CompanyID, @c_PeLi_CreatedBy,
@c_PeLi_CreatedDate, @c_PeLi_UpdatedBy, @c_PeLi_UpdatedDate, @c_PeLi_TimeStamp
--Fetch successful
--Check for a new row
WHILE @@FETCH_STATUS = 0
BEGIN
--EXEC @PersonLinkId = crm_next_id 31
INSERT INTO Person_Link
(
PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy,
PeLi_UpdatedDate, PeLi_TimeStamp
)
VALUES
(
@PersonLinkId, @PersonId, @CompanyId, @c_PeLi_CreatedBy, @c_PeLi_CreatedDate, '1', GETDATE(), @c_PeLi_TimeStamp
)
--Get next available row into variables
FETCH NEXT FROM @getPeLiID INTO @c_PeLi_PersonLinkId, @c_PeLi_PersonId, @c_PeLi_CompanyID, @c_PeLi_CreatedBy,
@c_PeLi_CreatedDate, @c_PeLi_UpdatedBy, @c_PeLi_UpdatedDate, @c_PeLi_TimeStamp
END
CLOSE @getPeLiID
DEALLOCATE @getPeLiID
------- Person Cursor -------------------------------------------------
-- Declare Variables
DECLARE @c_Pers_PersonId NVARCHAR(30)
DECLARE @c_Pers_CompanyId NVARCHAR(30)
DECLARE @c_Pers_PrimaryUserId NVARCHAR(30)
DECLARE @c_Pers_FirstName NVARCHAR(30)
DECLARE @c_Pers_SecTerr NVARCHAR(30)
DECLARE @c_Pers_CreatedBy NVARCHAR(30)
DECLARE @c_Pers_CreatedDate NVARCHAR(30)
DECLARE @c_Pers_UpdatedBy NVARCHAR(30)
DECLARE @c_Pers_UpdatedDate NVARCHAR(30)
DECLARE @c_Pers_TimeStamp NVARCHAR(30)
--Declare Cursor
DECLARE @getPersID CURSOR
SET @getPersID= CURSOR FOR
SELECT Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, Pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp
FROM Person
INNER JOIN Person_Link
ON Pers_PersonId = PeLi_PersonId
AND PeLi_CompanyID = @comp_companyid
--Open Cursor & fetch 1st row into variables
OPEN @getPersID
FETCH NEXT FROM @getPersID INTO @c_Pers_PersonId, @c_Pers_CompanyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName,
@c_Pers_SecTerr, @c_Pers_CreatedBy, @c_Pers_CreatedDate, @c_Pers_UpdatedBy,
@c_Pers_UpdatedDate, @c_Pers_TimeStamp
--Fetch successful
--Check for a new row
WHILE @@FETCH_STATUS = 0
BEGIN
--EXEC @PersonId = crm_next_id 13
INSERT INTO Person
(
Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, Pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp
)
VALUES
(
@PersonId, @companyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName, @c_Pers_SecTerr, @c_Pers_CreatedBy,
@c_Pers_CreatedDate, '1', GETDATE(), @c_Pers_TimeStamp
)
--Get next available row into variables
FETCH NEXT FROM @getPersID INTO @c_Pers_PersonId, @c_Pers_CompanyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName,
@c_Pers_SecTerr, @c_Pers_CreatedBy, @c_Pers_CreatedDate, @c_Pers_UpdatedBy,
@c_Pers_UpdatedDate, @c_Pers_TimeStamp
END
CLOSE @getPersID
DEALLOCATE @getPersID
Это моя структура таблицы:
компании Таблица:
comp_companyid | comp_primarypersonid | comp_primaryaddressid | comp_name
-------------------------------------------------------------------------
2 | 2 | 2 | company 2
3 | 3 | 3 | company 3
Person Таблица:
pers_personid | pers_companyid | pers_primaryaddressid | pers_name
-------------------------------------------------------------------------
2 | 2 | 2 | person 2
3 | 3 | 3 | person 3
4 | 2 | 2 | person 4
Person Ссылка Таблица:
peli_personlinkid | peli_personid | peli_companyid
-------------------------------------------------------------------------
2 | 2 | 2
3 | 3 | 3
У меня нет никакой проблемы, исполняющий хранимую процедуру, когда есть только один человек принадлежал к 1 компании, но когда компания имеет 2 человек и выше, ряд 2-го лица не будет дублироваться, только первый из них.
Сообщение об ошибке будет выскочить:
Msg 2627, Level 14, State 1, процедура DuplicateCompanyInfo, Линия 80
Нарушение ограничения PRIMARY KEY 'PK__Person_L__BCD268642CF2ADDF. Невозможно вставить дубликат ключа в объект «dbo.Person_Link».Msg 2627, Level 14, State 1, процедура DuplicateCompanyInfo, линия 141
Нарушение ограничения PRIMARY KEY 'PK__Person__381A5AC529221CFB. Невозможно вставить дубликат ключа в объект «dbo.Person».
я могу это исправить, удалив комментарий --EXEC @PersonLinkId = crm_next_id 31
& --EXEC @PersonID = crm_next_id 13
после того, как курсор начал так, что они будут генерировать новый идентификатор каждый раз, когда дублируется. Но это приведет к тому, что & Pers_PersonID
& PeLi_PersonID
не подсчитан, потому что каждый из них будет генерировать собственный новый идентификатор на основе их дублирования таблицы вместо применения внешних ключей друг друга.
Пожалуйста, помогите мне! Заранее благодарим за ваше время & усилием! Desmond
Зачем использовать курсоры? Кажется, это слишком сложно? –
Привет, сэр, см. Мой комментарий, который ответил на ответ Имрана ниже для объяснения. В таблицах может быть много повторяющихся записей, поэтому я хочу идти по строке за строкой с помощью курсора. –