--数据追溯查询 CREATE PROCEDURE [dbo].[proc_RecordFive] --查询条件 @productid varchar(50),--产品ID @mindate datetime,--最小时间 @maxdate datetime,--最大时间 @IsOk int, --是否合格 为空不查询 @startIndex int, --当前分页起始行 @EndIndex int, --当前分页结束行 --临时变量 @ProcessID varchar(50), @ItemSql nvarchar(max) AS BEGIN if @EndIndex>5000 RAISERROR('要查询的生产记录超出了5000条!',16,1) else begin --1.查找所有工序 对应字段 select c.F_Name as TTechniqueName,b.F_ID ProcessID,d.F_SortCode,b.F_Name ProcessName,a.F_Name AS ColText,f_ColName into #table1 from TProcessIOSet a right join TProcess b on a.F_VersionID=b.F_EffectiveVersionId right join TTechnique c on b.F_TechniqueID=c.f_id right join TTechniqueLine d on d.F_CurProcessID=b.F_id and d.F_TVersionID=c.F_EffectiveVersionId where c.F_ProductID=F_ProductID and a.F_Type=0 order by d.F_SortCode,a.f_ColName --2.查找所有生产记录 select * into #table2 from (select ROW_NUMBER() OVER (ORDER BY F_CreatorTime ASC) rowid, F_ProductCode,F_CreatorTime,lastIsok from( SELECT a.F_ProductCode,min(a.F_CreatorTime) F_CreatorTime,max(case d.F_NProcessID when '-1' then a.F_ISOK else 0 end) as lastIsok FROM TAllIDCode a left join TProcess b on a.F_ProcessID=b.F_Id left join TTechnique c on b.F_TechniqueID=c.f_id left join TTechniqueLine d on d.F_CurProcessID=b.F_id and d.F_TVersionID=c.F_EffectiveVersionId where c.F_ProductID=F_ProductID and a.F_CreatorTime BETWEEN @mindate AND @maxdate group by a.F_ProductCode ) _T where @IsOk is null or lastIsok=@IsOk) t where rowid BETWEEN @startIndex AND @EndIndex --3.打印所有列 select * from #table1 --4.打印所有生产 select * from #table2 --5.打印所有工序生产记录 declare Process_cur cursor for select ProcessID from #table1 group by ProcessID,F_SortCode order by F_SortCode open Process_cur fetch next from Process_cur into @ProcessID while (@@fetch_status=0) begin if exists (select * from sysobjects where id = object_id(N'TProductionDetail_'+replace(@ProcessID,'-','_')) and OBJECTPROPERTY(id, N'IsUserTable') = 1) begin set @ItemSql='select a.rowid,c.F_ISOK,c.F_ProductionTime,' select @ItemSql+='c.'+f_ColName+',' from #table1 where ProcessID=@ProcessID order by F_SortCode,f_ColName set @ItemSql +=' 0 as fakecol from #table2 a left join TAllIDCode b on b.F_ProductCode=a.F_ProductCode left join TProductionDetail_'+replace(@ProcessID,'-','_')+' c on c.f_id=b.F_KeyId where b.F_ProcessID='''+@ProcessID+''' ;' print @ItemSql exec sp_executesql @ItemSql end else select null fetch next from Process_cur into @ProcessID end close Process_cur deallocate Process_cur end end
时间: 2025-03-17 17:00:17 浏览: 35
<think>嗯,用户让我解释一下这个存储过程proc_RecordFive的作用,特别是关于数据追溯查询的部分。首先,我需要仔细看一下这个存储过程的代码结构,了解各个参数和步骤。
首先看参数部分,用户提供了产品ID、时间范围、是否合格、分页的起始和结束索引。这说明这个存储过程可能是用来分页查询某个产品在一定时间范围内的生产记录,并且可以根据是否合格进行筛选。临时变量@ProcessID和@ItemSql可能用于动态生成SQL语句。
接下来,存储过程内部的结构分为几个步骤。第一步是创建临时表#table1,通过多个right join关联了TProcessIOSet、TProcess、TTechnique和TTechniqueLine表,获取工序相关的信息,比如工序名称、排序码等。这里可能是在整理所有相关的工序数据,为后续查询做准备。
第二步是创建#table2,里面用到了ROW_NUMBER()窗口函数,按创建时间排序,并且筛选出在指定时间范围内的记录。同时,根据@IsOk参数判断是否合格,可能最后一道工序的状态决定了产品是否合格。这里的分页逻辑是通过rowid来限制查询结果的范围,避免一次性获取过多数据,但用户设定了最大5000条的限制,可能是为了防止性能问题。
第三步和第四步分别输出了#table1和#table2的结果,可能用于调试或直接返回部分数据。但真正的核心在第五步,这里使用了游标Process_cur遍历每个工序ID,动态生成SQL语句来查询每个工序的生产详情表,比如TProductionDetail_加上处理后的ProcessID。这里需要检查表是否存在,如果存在则拼接列名,执行动态SQL,否则返回空。
用户可能想知道这个存储过程如何实现数据追溯,也就是如何通过产品ID和时间等信息,查询到各个工序的生产记录。动态SQL部分可能是关键,因为它根据不同的工序动态连接不同的详情表,从而获取每个工序的具体生产数据。例如,每个工序可能有独立的表存储详细信息,存储过程通过循环每个工序,查询对应的表,并将结果返回。
需要注意的是,存储过程中使用了临时表和游标,这可能会影响性能,尤其是在处理大量数据时。另外,动态SQL的拼接存在SQL注入的风险,不过由于参数是内部生成的ProcessID,可能已经做了处理,但还是要确认是否有安全隐患。
用户可能的深层需求是了解如何优化这个存储过程,或者如何扩展其功能,比如增加更多的查询条件,或者提高查询效率。此外,数据追溯通常需要跨多个表关联查询,这个存储过程通过动态拼接的方式灵活处理不同工序的表结构,这可能是一个设计亮点,但也增加了维护的复杂性。
总结来说,这个存储过程proc_RecordFive主要用于分页查询特定产品的生产记录,包括各工序的详细信息,通过动态生成SQL实现多工序数据的联合查询,支持分页和合格状态过滤,适用于数据追溯场景。</think>以下是对该存储过程的逐步解析,重点围绕“数据追溯查询”功能展开:
---
### **一、存储过程功能概述**
该存储过程用于实现**产品全流程数据追溯**,支持分页查询、按时间范围/合格状态筛选,并动态关联各工序的详细生产数据表。
---
### **二、核心参数解析**
```sql
@productid varchar(50), -- 指定产品型号
@mindate datetime, -- 起始时间
@maxdate datetime, -- 结束时间
@IsOk int, -- 合格状态筛选 (0/1)
@startIndex int, -- 分页起始行
@EndIndex int -- 分页结束行(上限5000条)
```
---
### **三、关键步骤拆解**
#### **1. 构建工序元数据 (#table1)**
```sql
-- 关联工序配置表,获取工序名称、字段映射关系
SELECT c.F_Name AS TTechniqueName, b.F_ID ProcessID, ...
FROM TProcessIOSet a
RIGHT JOIN TProcess b ON ...
RIGHT JOIN TTechnique c ON ...
RIGHT JOIN TTechniqueLine d ON ...
WHERE c.F_ProductID = @productid
```
- **作用**:通过多表关联,确定当前产品型号关联的所有工序及其数据字段。
- **输出**:工序名称、字段名、排序码等元数据。
#### **2. 筛选生产记录 (#table2)**
```sql
-- 按时间范围获取产品基础记录,并标记最终合格状态
SELECT ROW_NUMBER() OVER (...) rowid, F_ProductCode, F_CreatorTime, lastIsok
FROM TAllIDCode a
LEFT JOIN TProcess b ON ...
LEFT JOIN TTechnique c ON ...
WHERE c.F_ProductID = @productid
AND a.F_CreatorTime BETWEEN @mindate AND @maxdate
GROUP BY a.F_ProductCode
HAVING (@IsOk IS NULL OR lastIsok = @IsOk)
```
- **核心逻辑**:
- 使用`ROW_NUMBER()`实现分页。
- 通过`F_NProcessID = '-1'`判断是否为最终工序的合格状态。
- 限制最大查询量5000条(防止性能问题)。
#### **3. 动态联查工序详情表**
```sql
-- 使用游标遍历所有工序,动态拼接SQL
DECLARE Process_cur CURSOR FOR
SELECT ProcessID FROM #table1 GROUP BY ProcessID ORDER BY F_SortCode;
OPEN Process_cur;
FETCH NEXT ...;
WHILE (@@FETCH_STATUS=0)
BEGIN
-- 动态生成查询语句,关联对应工序的详情表
SET @ItemSql = 'SELECT a.rowid, c.F_ISOK, ... FROM #table2 a
LEFT JOIN TAllIDCode b ON b.F_ProductCode = a.F_ProductCode
LEFT JOIN TProductionDetail_' + @ProcessID + ' c ...';
EXEC sp_executesql @ItemSql;
END
```
- **动态表名**:每个工序的详细数据存储在类似`TProductionDetail_[ProcessID]`的表中。
- **字段扩展**:根据#table1中的字段映射,动态选择需要查询的列。
---
### **四、设计特点分析**
1. **分页优化**
- 使用`ROW_NUMBER()`实现服务端分页,避免客户端全量传输。
- 强制限制查询量(5000条),防止资源耗尽。
2. **动态数据模型**
- 工序详情表按`ProcessID`动态命名,适应不同工序的异构数据结构。
3. **状态标记逻辑**
- 通过`F_NProcessID = '-1'`识别最终工序,确定产品整体合格状态。
---
### **五、潜在优化点**
1. **游标性能**
- 可尝试用`WHILE`循环替代游标,减少资源占用。
2. **动态SQL注入风险**
- 当前使用`REPLACE(@ProcessID,'-','_')`处理表名,需确保ProcessID格式严格受控。
3. **索引优化**
- 确保`TAllIDCode.F_CreatorTime`和`F_ProductCode`有复合索引。
---
### **六、典型应用场景**
1. **质量追溯**:快速定位某批次不合格产品的异常工序。
2. **生产统计**:按时间范围统计各工序合格率。
3. **工艺分析**:对比不同工序参数对最终质量的影响。
阅读全文
相关推荐


















