SQL 服务器:在存储过程中插入游标
SQL Server : Insert cursor within stored procedure
我是 SQL 服务器的新手,接到了一项任务,我必须使用游标复制 Phone Link table 的记录。其他 tables 我已经设法复制而不需要使用光标。但是我有 Phone Link table 的主键约束问题。有人可以帮助我吗?谢谢你。以下是我的存储过程。进气参数为comp_companyid。我的要求是将每一列复制到相同的 table 并生成新的主键和外键。
P/S:
- EntityID = 5(公司)
- EntityID = 13(人)
因为我还有人 phone 和人 phone link 之后还要补充。不过我只需要先解决这个问题,然后我做人的时候可以参考这个phone.
另外,一个公司可以有多个人,地址。
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
-- Add Person_Link Without Type
INSERT INTO Person_Link
(
PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy,
PeLi_UpdatedDate, PeLi_TimeStamp
)
SELECT
@PersonLinkId, @PersonId, @CompanyId, PeLi_CreatedBy,
PeLi_CreatedDate, '1', GETDATE(), PeLi_TimeStamp
FROM
Person_Link
WHERE
PeLi_CompanyID = @comp_companyid
-- Add Person
INSERT INTO Person
(
Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp
)
SELECT
@PersonId, @companyId, Pers_PrimaryUserId, Pers_FirstName,
pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, '1', GETDATE(), Pers_TimeStamp
FROM
Person
WHERE
Pers_CompanyId = @comp_companyid
-- Add Address_Link
INSERT INTO Address_Link
(
AdLi_AddressLinkId, AdLi_AddressId, AdLi_CompanyID, AdLi_CreatedBy, AdLi_CreatedDate,
AdLi_UpdatedBy, AdLi_UpdatedDate, AdLi_TimeStamp, AdLi_Type
)
SELECT
@AddressLinkId, @AddressId, @companyId, AdLi_CreatedBy,
AdLi_CreatedDate, '1', GETDATE(), AdLi_TimeStamp, AdLi_Type
FROM
Address_Link
WHERE
AdLi_CompanyID = @comp_companyid
-- Add Address
INSERT INTO [Address]
(
Addr_AddressId, Addr_Address1, Addr_Address2, Addr_Address3, Addr_Address4, addr_postcode,
Addr_CreatedBy, Addr_CreatedDate, Addr_UpdatedBy, Addr_UpdatedDate, Addr_TimeStamp
)
SELECT @AddressId, Addr_Address1, Addr_Address2, Addr_Address3, Addr_Address4, addr_postcode,
Addr_CreatedBy, Addr_CreatedDate, '1', GETDATE(), Addr_TimeStamp
FROM Address
INNER JOIN Address_Link
ON Addr_AddressId = AdLi_AddressId
AND AdLi_CompanyID = @comp_companyid
-- Add PhoneLink
-- Declare Variables
DECLARE @c_PLink_LinkID NVARCHAR(30)
DECLARE @c_PLink_PhoneId NVARCHAR(30)
DECLARE @c_PLink_CreatedBy NVARCHAR(30)
DECLARE @c_PLink_CreatedDate NVARCHAR(30)
DECLARE @c_PLink_UpdatedDate NVARCHAR(30)
DECLARE @c_PLink_TimeStamp NVARCHAR(30)
DECLARE @c_PLink_EntityID NVARCHAR(30)
DECLARE @c_PLink_RecordID NVARCHAR(30)
DECLARE @c_PLink_Type NVARCHAR(30)
DECLARE @c_Phon_PhoneId NVARCHAR(30)
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
--Declare Cursor
DECLARE @getPLID CURSOR
SET @getPLID= CURSOR FOR
SELECT PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
FROM PhoneLink
WHERE PLink_EntityID = 5
AND PLink_RecordID = @Comp_CompanyId
--Open Cursor & fetch 1st row into variables
OPEN @getPLID
FETCH NEXT FROM @getPLID INTO @c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy,
@c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
--Check for a new row
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
--Get next available row into variables
FETCH NEXT FROM @getPLID INTO @c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy,
@c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
CLOSE @getPLID
DEALLOCATE @getPLID
-- Add Company Phone
INSERT INTO Phone
(
Phon_PhoneId, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, Phon_UpdatedBy, Phon_UpdatedDate, Phon_TimeStamp
)
SELECT @PhoneID, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, '1', GETDATE(), Phon_TimeStamp
FROM Phone
INNER JOIN PhoneLink
ON Phon_PhoneId = PLink_PhoneId
AND PLink_EntityID = 5
AND PLink_RecordID = @Comp_CompanyId
END
如果你能告诉我哪一部分做错了,我将不胜感激。提前感谢您的时间和努力!
不确定所有插入的列的含义,但如果您要插入许多行,则需要为每一行生成另一个唯一 ID。因此,您必须将 ID 生成代码移动到游标主体中,而不是将其放在游标声明之前,并在每次迭代时调用此生成器。
...
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
FETCH NEXT FROM @getPLID
INTO @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate,
@c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
如果 PhoneID 也需要生成 - 您也必须将其放在光标内。
还要从游标的 select 中删除 PLink_LinkID 和 PLink_PhoneId,因为您不需要原始值。而且,当然,将它们从获取列表中删除。如上所示。
但是,
如果我的假设是正确的,那么你就走错了路。如果PhoneLink
table是一个table,links一些Phone到新创建的Entity/Company,那么你需要复制Phone 首先(并为该记录生成 ID),然后 - 在新的 Phone_ID 和新的 Company_ID 之间构建一个 link。
现在,如果每个公司始终只有一个 Phone(这会有点奇怪),那么您就不需要游标。但是,如果每个公司可以有多个 phone,那么您需要生成多个新的 Phone_ID。这意味着,您需要遍历 phones and links 而不是仅遍历 links。代码应如下所示:
...
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
INSERT INTO Phone
(
Phon_PhoneId, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, Phon_UpdatedBy, Phon_UpdatedDate, Phon_TimeStamp
)
SELECT @PhoneID, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, '1', GETDATE(), Phon_TimeStamp
FROM Phone
WHERE Phon_PhoneId = @Old_Phone_ID
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
FETCH NEXT FROM @getPLID
INTO @Old_Phone_ID, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate,
@c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
请注意,我已将 @Old_Phone_ID
返回到获取列表中 - 因此您可以通过 ID 找到复制的 phone。最后一个 insert-select-phone 在这种情况下不再需要(实际上在许多 phone 情况下是不正确的,因为它插入标量 @PhoneID,相同对于所有插入的行)。
我是 SQL 服务器的新手,接到了一项任务,我必须使用游标复制 Phone Link table 的记录。其他 tables 我已经设法复制而不需要使用光标。但是我有 Phone Link table 的主键约束问题。有人可以帮助我吗?谢谢你。以下是我的存储过程。进气参数为comp_companyid。我的要求是将每一列复制到相同的 table 并生成新的主键和外键。
P/S:
- EntityID = 5(公司)
- EntityID = 13(人)
因为我还有人 phone 和人 phone link 之后还要补充。不过我只需要先解决这个问题,然后我做人的时候可以参考这个phone.
另外,一个公司可以有多个人,地址。
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
-- Add Person_Link Without Type
INSERT INTO Person_Link
(
PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy,
PeLi_UpdatedDate, PeLi_TimeStamp
)
SELECT
@PersonLinkId, @PersonId, @CompanyId, PeLi_CreatedBy,
PeLi_CreatedDate, '1', GETDATE(), PeLi_TimeStamp
FROM
Person_Link
WHERE
PeLi_CompanyID = @comp_companyid
-- Add Person
INSERT INTO Person
(
Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp
)
SELECT
@PersonId, @companyId, Pers_PrimaryUserId, Pers_FirstName,
pers_SecTerr, Pers_CreatedBy,
Pers_CreatedDate, '1', GETDATE(), Pers_TimeStamp
FROM
Person
WHERE
Pers_CompanyId = @comp_companyid
-- Add Address_Link
INSERT INTO Address_Link
(
AdLi_AddressLinkId, AdLi_AddressId, AdLi_CompanyID, AdLi_CreatedBy, AdLi_CreatedDate,
AdLi_UpdatedBy, AdLi_UpdatedDate, AdLi_TimeStamp, AdLi_Type
)
SELECT
@AddressLinkId, @AddressId, @companyId, AdLi_CreatedBy,
AdLi_CreatedDate, '1', GETDATE(), AdLi_TimeStamp, AdLi_Type
FROM
Address_Link
WHERE
AdLi_CompanyID = @comp_companyid
-- Add Address
INSERT INTO [Address]
(
Addr_AddressId, Addr_Address1, Addr_Address2, Addr_Address3, Addr_Address4, addr_postcode,
Addr_CreatedBy, Addr_CreatedDate, Addr_UpdatedBy, Addr_UpdatedDate, Addr_TimeStamp
)
SELECT @AddressId, Addr_Address1, Addr_Address2, Addr_Address3, Addr_Address4, addr_postcode,
Addr_CreatedBy, Addr_CreatedDate, '1', GETDATE(), Addr_TimeStamp
FROM Address
INNER JOIN Address_Link
ON Addr_AddressId = AdLi_AddressId
AND AdLi_CompanyID = @comp_companyid
-- Add PhoneLink
-- Declare Variables
DECLARE @c_PLink_LinkID NVARCHAR(30)
DECLARE @c_PLink_PhoneId NVARCHAR(30)
DECLARE @c_PLink_CreatedBy NVARCHAR(30)
DECLARE @c_PLink_CreatedDate NVARCHAR(30)
DECLARE @c_PLink_UpdatedDate NVARCHAR(30)
DECLARE @c_PLink_TimeStamp NVARCHAR(30)
DECLARE @c_PLink_EntityID NVARCHAR(30)
DECLARE @c_PLink_RecordID NVARCHAR(30)
DECLARE @c_PLink_Type NVARCHAR(30)
DECLARE @c_Phon_PhoneId NVARCHAR(30)
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
--Declare Cursor
DECLARE @getPLID CURSOR
SET @getPLID= CURSOR FOR
SELECT PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
FROM PhoneLink
WHERE PLink_EntityID = 5
AND PLink_RecordID = @Comp_CompanyId
--Open Cursor & fetch 1st row into variables
OPEN @getPLID
FETCH NEXT FROM @getPLID INTO @c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy,
@c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
--Check for a new row
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
--Get next available row into variables
FETCH NEXT FROM @getPLID INTO @c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy,
@c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
CLOSE @getPLID
DEALLOCATE @getPLID
-- Add Company Phone
INSERT INTO Phone
(
Phon_PhoneId, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, Phon_UpdatedBy, Phon_UpdatedDate, Phon_TimeStamp
)
SELECT @PhoneID, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, '1', GETDATE(), Phon_TimeStamp
FROM Phone
INNER JOIN PhoneLink
ON Phon_PhoneId = PLink_PhoneId
AND PLink_EntityID = 5
AND PLink_RecordID = @Comp_CompanyId
END
如果你能告诉我哪一部分做错了,我将不胜感激。提前感谢您的时间和努力!
不确定所有插入的列的含义,但如果您要插入许多行,则需要为每一行生成另一个唯一 ID。因此,您必须将 ID 生成代码移动到游标主体中,而不是将其放在游标声明之前,并在每次迭代时调用此生成器。
...
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
FETCH NEXT FROM @getPLID
INTO @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate,
@c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
如果 PhoneID 也需要生成 - 您也必须将其放在光标内。 还要从游标的 select 中删除 PLink_LinkID 和 PLink_PhoneId,因为您不需要原始值。而且,当然,将它们从获取列表中删除。如上所示。
但是,
如果我的假设是正确的,那么你就走错了路。如果PhoneLink
table是一个table,links一些Phone到新创建的Entity/Company,那么你需要复制Phone 首先(并为该记录生成 ID),然后 - 在新的 Phone_ID 和新的 Company_ID 之间构建一个 link。
现在,如果每个公司始终只有一个 Phone(这会有点奇怪),那么您就不需要游标。但是,如果每个公司可以有多个 phone,那么您需要生成多个新的 Phone_ID。这意味着,您需要遍历 phones and links 而不是仅遍历 links。代码应如下所示:
...
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @c_PLink_LinkID = crm_next_id 10208
EXEC @c_PLink_PhoneId = crm_next_id 14
INSERT INTO Phone
(
Phon_PhoneId, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, Phon_UpdatedBy, Phon_UpdatedDate, Phon_TimeStamp
)
SELECT @PhoneID, Phon_Number, Phon_CreatedBy, Phon_CreatedDate, '1', GETDATE(), Phon_TimeStamp
FROM Phone
WHERE Phon_PhoneId = @Old_Phone_ID
INSERT INTO PhoneLink
(
PLink_LinkID, PLink_PhoneId, PLink_CreatedBy, PLink_CreatedDate, PLink_UpdatedDate, PLink_TimeStamp,
PLink_EntityID, PLink_RecordID, PLink_Type
)
VALUES
(
@c_PLink_LinkID, @c_PLink_PhoneId, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate, @c_PLink_TimeStamp,
@c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
)
FETCH NEXT FROM @getPLID
INTO @Old_Phone_ID, @c_PLink_CreatedBy, @c_PLink_CreatedDate, @c_PLink_UpdatedDate,
@c_PLink_TimeStamp, @c_PLink_EntityID, @c_PLink_RecordID, @c_PLink_Type
END
请注意,我已将 @Old_Phone_ID
返回到获取列表中 - 因此您可以通过 ID 找到复制的 phone。最后一个 insert-select-phone 在这种情况下不再需要(实际上在许多 phone 情况下是不正确的,因为它插入标量 @PhoneID,相同对于所有插入的行)。