【问题标题】:Using a Cursor inside a Stored Procedure to Write to a Table from Multiple Tables在存储过程中使用游标从多个表中写入表
【发布时间】:2014-11-14 21:09:15
【问题描述】:

我正在努力编写我的第一个过程,将多个表中的数据拉到一起,然后使用游标将其写入另一个表以循环所有数据。希望在这里找到一些帮助。

我将 6 个表连接回主表 Accounts,以显示所需的数据。使用第一个光标,我连接了五个表以获取所需的信息,然后我想再添加两个光标以从添加到表中的电话详细信息表中获取电话号码(主要和次要)。

希望这是有道理的。我确定我在 SQL 中遗漏了一些东西,但基本上我想遍历 Accounts 表并将数据写入一个新表,并遍历 Phone Detail 表并获取每个帐户的主要电话和然后辅助电话(同时考虑 NULL 值)也将其写入新表。

CREATE PROCEDURE [dbo].[CRM_Account_Info] 
    @AccountID int,
    @AccountName nvarchar(128),
    @Bus_Type nvarchar(50),
    @AccountAddr1 nvarchar(128),
    @AccountAddr2 nvarchar(128),
    @AccountCity nvarchar(32),
    @AccountState nvarchar(10),
    @AccountZip nvarchar(10),
    @Account_Coll_Area_CodeID int,
    @Account_Coll_Area nvarchar(50),
    @Account_CRC_ID int,
    @Account_CRC_Name nvarchar(100),
    @Account_Prime_Number nvarchar(120),
    @Account_2nd_Number nvarchar(120)
AS
BEGIN
    -- Truncate Accounts table 
    Execute Immediate 'Truncate DBO.CRM_Accounts';

    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Grab Account ID, Account Name, Account Type, Address, City, State, Zip, Collection Area ID, Collection Area Description,
    -- Recruiter ID, Recruiter Full Name from the Accounts Table

    Declare Acct_Info cursor for
        Select 
           Acct.AccountID, Acct.Internalname, 
           QC.Descshort, 
           AD.Addr1, AD.Addr2, AD.City, AD.State, AD.Zip,
           Sub.CodeID, Sub.Description, 
           Peo.PersonID, Peo.Fullname
        from 
           Accounts as Acct
        inner join 
           AddressDetail AD on Acct.AccountID = AD.AccountID
        inner join 
           CenterDetail CD on Acct.Centerid = CD.CenterID
        inner join 
           People Peo on Acct.LeaderID = Peo.PersonID
        inner join 
           IDViewOrgSubCenter SUB on CD.OrgSubCenter = SUB.CodeID
        inner join 
           QuickCodes QC on Acct.AccountType = QC.CodeID

    Open Acct_Info -- Open cursor

    Fetch Next from Acct_Info into @AccountID, @AccountName, @Bus_Type, @AccountAddr1, 
                                   @AccountAddr2, @AccountCity, @AccountState, @AccountZip,
                                   @Account_Coll_Area_CodeID, @Account_Coll_Area, 
                                   @Account_CRC_ID, @Account_CRC_Name, @Account_Prime_Number, 
                                   @Account_2nd_Number

    Close Acct_Info  -- Close cursor

    -- Grab the Primary Phone for the Account
    Declare Primary_Phone cursor for

Select top 1 Acct.AccountID, PD.FormattedNumber
From PhoneDetail PD
inner join Accounts Acct on PD.AccountID=Acct.AccountID
Where PD.PrimaryPhone=1
And PD.AccountID=@AccountID

Close Primary_Phone  -- Close cursor

-- Grab the second phone for an account

Declare Secondary_Phone cursor for

Select top 1 Acct.AccountID, PD.FormattedNumber
From PhoneDetail PD
inner join Accounts Acct on PD.AccountID=Acct.AccountID
Where PD.PrimaryPhone<>1
And PD.AccountID=@AccountID

Close Secondary_Phone  -- Close cursor

-- Insert the values into the CRM table
Insert CRM_Accounts (
AccountID,
AccountName,
Bus_Type,
AccountAddr1,
AccountAddr2,
AccountCity,
AccountState,
AccountZip,
Account_Coll_Area_CodeID,
Account_Coll_Area,
Account_CRC_ID,
Account_CRC_Name,
Account_Prime_Number,
Account_2nd_Number
)
Values (
@AccountID,
@AccountName,
@Bus_Type,
@AccountAddr1,
@AccountAddr2,
@AccountCity,
@AccountState,
@AccountZip,
@Account_Coll_Area_CodeID,
@Account_Coll_Area,
@Account_CRC_ID,
@Account_CRC_Name,
@Account_Prime_Number,
@Account_2nd_Number
)
END
GO

【问题讨论】:

  • 你能写一个单一的选择来获取你需要的所有数据吗?如果是这样,那么一个简单的INSERT INTO...SELECT 可以让你在不使用游标的情况下到达那里。
  • 我已经尝试过了,但是当从同一个表中提取多个电话号码时,我无法弄清楚如何编写单个选择。
  • 所以一个帐户可以有多个电话号码,其中primaryphone = 1?一个帐户还可以有多个电话号码,其中primaryphone 1?我假设这是因为您使用了TOP 1
  • 你加入了一张桌子两次。你只需要用两种不同的方式给它起别名。我会加入 PhoneDetail 两次:一次是 PrimaryPhone = 1,另一次是 PrimaryPhone 1。
  • 正确,一个帐户可以有多个电话号码,不幸的是,它可以有多个主要电话号码(尽管不应该)。不幸的是,我今天发现了一个案例并纠正了它,但我想让这个故障安全,以防它再次发生。

标签: sql stored-procedures cursor


【解决方案1】:

试试这个以在一个查询中获取所有内容。我做了 2 个派生表,一个是主表,一个是辅助表,并给它们按 accountid 分区的行号。然后在连接中,我只得到 rownumber = 1 以便每个 accountid 只返回一个数字。

 SELECT Acct.accountid,
       Acct.internalname,
       QC.descshort,
       AD.addr1,
       AD.addr2,
       AD.city,
       AD.state,
       AD.zip,
       Sub.codeid,
       Sub.description,
       Peo.personid,
       Peo.fullname,
       pd1.formattedNumber,
       pd2.formattedNumber
FROM   accounts AS Acct
       INNER JOIN addressdetail AD
               ON Acct.accountid = AD.accountid
       INNER JOIN centerdetail CD
               ON Acct.centerid = CD.centerid
       INNER JOIN people Peo
               ON Acct.leaderid = Peo.personid
       INNER JOIN idvieworgsubcenter SUB
               ON CD.orgsubcenter = SUB.codeid
       INNER JOIN quickcodes QC
               ON Acct.accounttype = QC.codeid  
       LEFT JOIN (select accountid, formattednumber, primaryphone, row_number() over(partition by accountid order by formattednumber) as rNum  
                           from phonedetail where primaryphone = 1) pd1
                ON acct.accountid = pd1.accountid and pd1.rNum = 1
       LEFT JOIN (select accountid, formattednumber, primaryphone, row_number() over(partition by accountid order by formattednumber) as rNum  
                           from phonedetail where primaryphone <> 1) pd2
                ON acct.accountid = pd2.accountid and pd2.rNum = 1

【讨论】:

  • 谢谢@JChao。小修改,我必须将“和 pd.rNum = 1 更改为 pd1.rNum 和 pd2 相同。但这似乎工作得很好。
  • @MISNole 对此感到抱歉。我在看到错误后不久就进行了编辑。
  • 无需道歉,我一直在努力解决这个问题,非常感谢您的帮助。
【解决方案2】:

@JChao,我将把你的答案标记为正确,因为 SQL 工作得很好,但我想根据收到的建议在此处发布此内容,并让更多的目光现在查看此过程。它似乎有效,但我希望更有经验的用户检查一下,看看他们是否发现任何明显的错误:

第一步是删除(或截断)当前表中的所有数据,然后将 select 语句写入我的新表中:

Create Procedure Update_CRM_Accts
--Alter Procedure Update_CRM_Accts
As
Begin
Truncate Table CRM_Accounts
SET NOCOUNT ON;
Insert into CRM_Accounts
Select Acct.AccountID,
   Acct.InternalName,
   QC.DescShort,
   AD.Addr1,
   AD.Addr2,
   AD.City,
   AD.State,
   AD.Zip,
   Sub.CodeID,
   Sub.Description,
   Peo.PersonID,
   Peo.FullName,
   PD1.FormattedNumber as 'Primary_Number',
   PD2.FormattedNumber as 'Secondary_Number'
From Accounts As Acct
INNER JOIN addressdetail AD ON Acct.AccountID = AD.AccountID
INNER JOIN CenterDetail CD ON Acct.CenterID = CD.CenterID
INNER JOIN People Peo ON Acct.LeaderID = Peo.PersonID
INNER JOIN IDViewOrgSubCenter SUB ON CD.OrgSubcenter = SUB.CodeID
INNER JOIN quickcodes QC ON Acct.AccountType = QC.CodeID  
LEFT OUTER JOIN (Select AccountID, FormattedNumber, PrimaryPhone, row_number() over(partition by AccountID order by FormattedNumber) as rNum  
       From PhoneDetail where PrimaryPhone = 1) PD1
            ON Acct.accountid = PD1.AccountID and PD1.rNum = 1
LEFT OUTER JOIN (Select AccountID, FormattedNumber, PrimaryPhone, row_number() over(partition by AccountID order by FormattedNumber) as rNum  
       From PhoneDetail where PrimaryPhone <> 1) PD2
            ON Acct.AccountID = PD2.AccountID and PD2.rNum = 1
End
Go

【讨论】:

    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 2015-02-14
    • 2021-12-29
    • 1970-01-01
    相关资源
    最近更新 更多