我如何重写它以避免光标
Posted
技术标签:
【中文标题】我如何重写它以避免光标【英文标题】:How do I rewrite this to avoid a cursor 【发布时间】:2018-03-10 06:30:43 【问题描述】:我在 SQL Server 2005 上用 T-SQL 编写了这个函数。我不像某些人那样反对游标,但我总是看到人们说 99% 的游标可以重写以避免使用它们。
我有这个功能:
CREATE FUNCTION WhereUsed(@ItemID varchar(100))
RETURNS varchar(MAX)
AS
BEGIN
DECLARE @Items CURSOR
DECLARE @ParentItem varchar(100)
DECLARE @WhereUsed varchar(MAX)
SET @WhereUsed = ''
SET @Items = CURSOR FAST_FORWARD
FOR
SELECT PST_ParentItemID FROM PST WHERE PST_CompItemID = @ItemID
OPEN @Items
FETCH NEXT FROM @Items
INTO @ParentItem
WHILE @@FETCH_STATUS = 0
BEGIN
SET @WhereUsed = @WhereUsed + @ParentItem + ', '
FETCH NEXT FROM @Items
INTO @ParentItem
END
IF LEN(@WhereUsed) > 2
SET @WhereUsed = LEFT(@WhereUsed, LEN(@WhereUsed) - 2)
RETURN @WhereUsed
END
这将获取使用零件的所有项目,PST 是 ParentStructureTable。想想 BOM(物料清单)
会这样使用:
SELECT Field1, Field2, dbo.WhereUsed(ItemID), Field3 FROM Item
并返回如下内容:
S6110-23350-41, 61070-10161-012, R6112-23027-41
不使用光标怎么办?
编辑: 样本数据
SELECT PST_ParentItemID FROM PST WHERE PST_CompItemID = @ItemID
可以返回
PST_ParentItemID
----------------
S6110-23350-41
61070-10161-012
R6112-23027-41
它确实是一个简单的选择语句,不确定 DDL 将如何提供帮助,但它是:
CREATE TABLE [dbo].[ProductStructure](
[PST_RecordID] [uniqueidentifier] NOT NULL,
[PST_PSH_RecordID] [uniqueidentifier] NOT NULL,
[PST_IMA_RecordID] [uniqueidentifier] NOT NULL,
[PST_EffStartDate] [datetime] NOT NULL,
[PST_EffStopDate] [datetime] NULL,
[PST_DisplayOrder] [int] NOT NULL CONSTRAINT [DF__ProdStruc__PST_DisplayOrder] DEFAULT ((0)),
[PST_Available] [bit] NOT NULL CONSTRAINT [DF__ProdStruc__PST_Available] DEFAULT ((1)),
[PST_AddDate] [datetime] NOT NULL CONSTRAINT [DF__ProdStruc__PST_AddDate__192BAC54] DEFAULT (getdate()),
[PST_QtyPerAssy] [float] NOT NULL CONSTRAINT [DF__ProdStruc__PST_QtyPerA__1A1FD08D] DEFAULT ((1)),
[PST_ScrapQty] [float] NOT NULL CONSTRAINT [DF__ProdStruc__PST_ScrapQt__1B13F4C6] DEFAULT ((0)),
[PST_PlanType] [nvarchar](11) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF__ProdStruc__PST_PlanTyp__1C0818FF] DEFAULT ('MRP'),
[PST_ScrapPercent] [float] NOT NULL CONSTRAINT [DF__ProdStruc__PST_ScrapPe__1CFC3D38] DEFAULT ((0)),
[PST_LeadTimeOffsetDays] [smallint] NOT NULL CONSTRAINT [DF__ProdStruc__PST_LeadTim__1DF06171] DEFAULT ((0)),
[PST_RoutSeqID] [nvarchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_EngChangeOrderID] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_FindID] [nvarchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_Comments] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_UseAbsQtyFlag] [bit] NOT NULL CONSTRAINT [DF__ProdStruc__PST_UseAbsQ__1EE485AA] DEFAULT ((0)),
[PST_IgnoreCostFlag] [bit] NOT NULL CONSTRAINT [DF__ProdStruc__PST_IgnoreC__1FD8A9E3] DEFAULT ((0)),
[PST_PlanningPercent] [float] NOT NULL CONSTRAINT [DF__ProdStruc__PST_Plannin__20CCCE1C] DEFAULT ((0)),
[PST_EMP_RecordID] [uniqueidentifier] NULL,
[PST_LastModifiedDate] [datetime] NULL,
[PST_PurchPOWO] [bit] NOT NULL CONSTRAINT [DF__ProdStruc__PST_PurchPO__21C0F255] DEFAULT ((0)),
[PST_AgileCreatedDate] [datetime] NULL,
[PST_ArchiveDate] [datetime] NULL,
[PST_UserDef1] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_UserDef2] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_UserDef3] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_UserDef4] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PST_UserDef5] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[timestamp] [timestamp] NULL,
[PST_SWImportFlag] [bit] NOT NULL CONSTRAINT [DF_ProductStructure_PST_SWImportFlag] DEFAULT ((0)),
[PST_CopiedFromRecordID] [uniqueidentifier] NULL,
[PST_OnPicklist] [bit] NOT NULL DEFAULT ((1)),
[PST_CID_DocumentID] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_ProductStructure] PRIMARY KEY NONCLUSTERED
(
[PST_RecordID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
【问题讨论】:
能否给出表格的DDL或一些示例数据?这真的只是看起来像一个奇怪的结构化派生表。 【参考方案1】:看来您只是在返回一个串联的字符串。试试这个
DECLARE @WhereUsed varchar(MAX)
SET @WhereUsed = ''
SELECT @whereUsed=@whereUsed+PST_ParentItemID+', 'FROM PST
WHERE PST_CompItemID = @ItemID
IF LEN(@WhereUsed) > 2
SET @WhereUsed = LEFT(@WhereUsed, LEN(@WhereUsed) - 2)
【讨论】:
不错!我不知道我可以在 select 语句中构建一个字符串。我会改变我的功能。以上是关于我如何重写它以避免光标的主要内容,如果未能解决你的问题,请参考以下文章