T-SQL——关于XML类型_SQL解析XML

0.前提背景

0.1 背景

新接手一个MES,这个MES系统的整体架构是基于WPF,

其中这个架构中的接口或存储过程中的数据都是以XML格式进行传递的

所以经常出现传递一个XML类型的数据到存储过程中,然后在存储过程中进行解析

故整理一下关于SQL解析XML的方式,方便查阅

0.2 关于XML类型

  • 关于XML的基本概念

    • 元素:<Student><Name>Tom</Name></Student>,这里的Name就是元素
    • 属性: <Student Name="Tom"/>,这里的Name就是属性
    • 文本:<Name>Tom</Name>,这里的Tom就是文本
    • 无论是采用元素还是属性的方式表达数据信息,最终表达的效果是一样的。但是,我们要注意:应该尽量避免使用属性。对于大多数情况,推荐将实体属性转为XML元素。这符合XML的最佳实践,提供了更好的可读性和可维护性
      • 0.属性难以阅读和维护。请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息
      • 1.属性无法包含多重的值(元素可以)
      • 2.属性值不能包含子节点(元素可以)
      • 3.属性不易扩展(为未来的变化)
      • 4.对比下面两种XML格式的区别:仅在属性较少且数据结构简单的情况下,使用属性可以提高XML的简洁性
  • 推荐:

    <Class  Count=2>
        <ClassId>1<ClassId>
        <ClassName>1班</ClassName>
        <Student>
            <Id>1001</Id>
            <Name>Tom</Name >
            <Age>30</Age>
        </Student>
        <Student>
            <Id>1002</Id>
            <Name>Jerry</Name >
            <Age>30</Age>
        </Student>
    </Class>
    
  • 不推荐

    <Class Classid="1" ClassName="1班" Count="2">
        <Student Id="1001" Name="Tom" Age="30" />
        <Student Id="1002" Name="Jerry" Age="30" />
    </Class>
    
  • 数据库中为什么要使用XML类型?

    • 1.如果数据结构明确,则关系模型最适合数据存储,若是数据结构是非结构化的或者是未知的,则可以保存为XML数据
    • 2.将数据存储在 XML 列中还有其他好处, 包括让引擎确定数据格式是否正确或有效,以及支持对 XML 数据进行精细查询和更新。
    • 3.存储数据的精确副本。 这对于特殊用途的应用(如法律文档)很有用。 大多数应用不需要完全相同的副本,且 XML 内容(InfoSet 保真度)即可满足需要
  • 操作XML的方法:通过使用 nodesmodify方法,可以直接在XML数据上执行XPath表达式进行读取、更新、插入和删除操作

    • 读取节点:使用 nodes() 方法和 value()` 方法。
    • 更新节点:使用 modify() 方法的 replace value of 子句。
    • 插入节点:使用 modify() 方法的 insert 子句。
    • 删除节点:使用 modify() 方法的 delete 子句。

0.3 XPATH基础语法

  • 说明:XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

  • XPath语法:参考XPath 语法

    • XPATH是XQuery 的基础,其获取指定节点的语法很强大,这里不罗列了,详见上述参考连接
    • 下面的示例,仅仅是如何获取节点和获取元素属性,其他的并没有使用太多的XPATH语法。
      • 因为我的使用场景不太一样,我只是将XML类型当做存储过程的参数,并完整的解析为表值,所以并不涉及太多对XML的操作
      • 其二,我看网上好多是都直接在XML中筛选查找指定的节点,我还是习惯将XML结构转为表值,在用SQL进行筛选操作

1.构造测试数据

  • 定义实体类
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public List<string> Hobbies { get; set; }
    public Address StudentAddress { get; set; }
    public List<Course> ListCourse { get; set; }
}

//这里使用XmlAttribute将Address中的属性定义为XML中的属性
//示例开发中不建议这么做,这里只是为了演示
[XmlType("Address")]
public class Address
{
    [XmlAttribute("Code")]
    public int Code { get; set; }
    [XmlAttribute("Region")]
    public string Region { get; set; }
    [XmlAttribute("City")]
    public string City { get; set; }
    [XmlAttribute("Province")]
    public string Province { get; set; }
}

//这里使用XmlElement将Course中的属性定义为片为XML中的元素
[XmlType("Course")]
public class Course
{
    [XmlElement("CourseId")]
    public int CourseId { get; set; }
    [XmlElement("CourseName")]
    public string CourseName { get; set; }
}

  • 创建一个实例,并序列化为XML
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

Student student = new Student()
{
    Id = 1,
    Age = 30,
    Name = "Tom",
    Hobbies = new List<string>() { "Baskball", "Football" },
    StudentAddress = new Address() { Code = 1, Region = "HuoDong", Province ="JiangSu",City ="Suzhou" },
    ListCourse = new List<Course>() { new Course() { CourseId = 100, CourseName="Chinese" },new Course() { CourseId = 101, CourseName = "Math" } }
};

XmlSerializer serializer = new XmlSerializer(typeo(Student));
using (StringWriter writer = new StringWriter())
{
    serializer.Serialize(writer, student);
    string xmlStudent = writer.ToString();
    Console.WriteLine(xmlStudent);
}

2.SQL读取XML节点及属性

  • 声明一个XML类型,并初始化
DECLARE @xml XML;
SET @xml='
<Student>
    <Id>1</Id>
    <Name>Tom</Name>
    <Age>30</Age>
    <Hobbies>
        <string>Baskball</string>
        <string>Football</string>
    </Hobbies>
    <StudentAddress Code="1" Region="HuoDong" City="Suzhou" Province="JiangSu" />
    <ListCourse>
        <Course>
            <CourseId>100</CourseId>
            <CourseName>Chinese</CourseName>
        </Course>
        <Course>
            <CourseId>101</CourseId>
            <CourseName>Math</CourseName>
        </Course>
    </ListCourse>
</Student>';

  • 解析Student对象的常规属性
--解析Student
SELECT x.value('./Id[1]', 'int')             AS Id
      ,x.value('./Name[1]', 'nvarchar(100)') AS Name
      ,x.value('./Age[1]', 'int')            AS Age
FROM  @xml.nodes('/Student') T(x);

结果:

Id Name Age
1 Tom 30
  • 解析List类型属性
--解析Hobbies(这种方式无意义,因为Hobbies中的元素个数不确定)
SELECT x.value('string[1]', 'nvarchar(100)') AS Hobby1, x.value('string[2]', 'nvarchar(100)') AS Hobby2
FROM  @xml.nodes('/Student/Hobbies') T(x);

结果:

Hobby1 Hobby2
Baskball Football
--解析Hobbies
SELECT x.value('.', 'nvarchar(100)') AS Hobbies FROM @xml.nodes('/Student/Hobbies/string') T(x);

结果:

Hobbies
Baskball
Football
  • 解析自定义类型Address

注意:我们在序列化的时候,Address类中的属性Code,Region,City,Province全部是使用特性[XmlAttribute],故这些属性在XML中为标签的属性

--解析StudenAddress
SELECT x.value('@Code', 'nvarchar(100)')     AS Code
      ,x.value('@Region', 'nvarchar(100)')   AS Region
      ,x.value('@City', 'nvarchar(100)')     AS City
      ,x.value('@Province', 'nvarchar(100)') AS Province
FROM  @xml.nodes('/Student/StudentAddress') T(x);

结果:

Code Region City Province
1 HuoDong Suzhou JiangSu
  • 解析自定义类型Course

注意:我们的序列化的时候,Course类中的属性CourseId,CourseName全部(默认)是使用特性[XmlElement],故这些属性在XML中为标签

--解析ListCourse
SELECT x.value('(CourseId/text())[1]', 'int')            AS CourseId
      ,x.value('(CourseName/text())[1]', 'nvarchar(50)') AS CourseName
FROM  @xml.nodes('/Student/ListCourse/Course') AS T(x);

结果:

CourseId CourseName
100 Chinese
101 Math

3.SQL编辑XML节点

3.1 SQL更新XML节点

示例:更新 CourseId 为 100 的 CourseName 为 "English"

DECLARE @xml XML;
SET @xml = '
<ListCourse>
    <Course>
        <CourseId>100</CourseId>
        <CourseName>Chinese</CourseName>
    </Course>
    <Course>
        <CourseId>101</CourseId>
        <CourseName>Math</CourseName>
    </Course>
</ListCourse>';

-- 更新 CourseId 为 100 的 CourseName 为 "English"
SET @xml.modify('
    replace value of (/ListCourse/Course[CourseId=100]/CourseName/text())[1] with "English"
');

-- 读取更新后的 XML
SELECT 
    T.c.value('(CourseId/text())[1]', 'int') AS CourseId,
    T.c.value('(CourseName/text())[1]', 'nvarchar(50)') AS CourseName
FROM 
    @xml.nodes('/ListCourse/Course') AS T(c);

结果:

CourseId CourseName
100 English
101 Math

3.2 插入新节点

示例:插入一个新的 Course 节点

DECLARE @xml XML;
SET @xml = '
<ListCourse>
    <Course>
        <CourseId>100</CourseId>
        <CourseName>Chinese</CourseName>
    </Course>
    <Course>
        <CourseId>101</CourseId>
        <CourseName>Math</CourseName>
    </Course>
</ListCourse>';

-- 插入一个新的 Course 节点
SET @xml.modify('
    insert <Course>
        <CourseId>102</CourseId>
        <CourseName>Science</CourseName>
    </Course>
    as last into (/ListCourse)[1]
');

-- 读取更新后的 XML
SELECT 
    T.c.value('(CourseId/text())[1]', 'int') AS CourseId,
    T.c.value('(CourseName/text())[1]', 'nvarchar(50)') AS CourseName
FROM 
    @xml.nodes('/ListCourse/Course') AS T(c);

结果:

CourseId CourseName
100 Chinese
101 Math
102 Science

3.3 删除节点

示例:删除 CourseId 为 101 的 Course 节点

DECLARE @xml XML;
SET @xml = '
<ListCourse>
    <Course>
        <CourseId>100</CourseId>
        <CourseName>Chinese</CourseName>
    </Course>
    <Course>
        <CourseId>101</CourseId>
        <CourseName>Math</CourseName>
    </Course>
</ListCourse>';

-- 删除 CourseId 为 101 的 Course 节点
SET @xml.modify('
    delete /ListCourse/Course[CourseId=101]
');

-- 读取更新后的 XML
SELECT 
    T.c.value('(CourseId/text())[1]', 'int') AS CourseId,
    T.c.value('(CourseName/text())[1]', 'nvarchar(50)') AS CourseName
FROM 
    @xml.nodes('/ListCourse/Course') AS T(c);

结果:

CourseId CourseName
100 Chinese

4.对XML的节点做一些判断

  • 首先,我们还是可以将XML的节点数据转为表值,使用SQL进行统计判断,但是这里还是罗列一些直接针对XML的判断方法

4.1 判断是否存在指定类型的节点

  • 判断ListCourse节点下是否存在Course节点
DECLARE @xml XML='<ListCourse>
    <Course>
        <CourseId>100</CourseId>
        <CourseName>Chinese</CourseName>
    </Course>
</ListCourse>';

SELECT CASE @xml.exist('ListCourse/Course')WHEN 1 THEN 'true' ELSE 'false' END AS IsExist;

--结果:
IsExist
--------
true

4.2 统计指定类型的节点数量

  • 得到XML类型中某个节点下子节点的数量,这在需要验证或处理特定数量的参数时非常有用

这里演示统计ListCourse节点下Course节点的数量

DECLARE @xml XML =
'<ListCourse>
    <Course>
        <CourseId>100</CourseId>
        <CourseName>Chinese</CourseName>
    </Course>
    <Course>
        <CourseId>101</CourseId>
        <CourseName>Math</CourseName>
    </Course>
</ListCourse>'

SELECT c.value('count(/ListCourse/Course)','int') AS  CourseCount FROM  @xml.nodes('/ListCourse') T(c)

SELECT @xml.value('count(/ListCourse/Course)','int') AS CourseCount

--结果:
2

5.示例—:一个使用XML类型参数的存储过程

说明:

  • 这个是一个解析客户端传来的XML的简单示例,该XML数据是ERP下发工单到MES的参数
    实际开发中是创建一个存储过程,该存储过程的参数是XML类型的,然后该存储过程中的解析XML,并进行一些处理
    这个XML参数格式,并不是最佳的实践方式,还是应该使用元素表示数据而不是使用属性表示数据。

  • 解析XML看似繁琐,但是因为参数是XML类型的,可以让存储过程一次性接受大量的结构化的数据,故可以一次性将所需的参数都传递到存储过程
    尤其是开发接口的时候,接口参数为一个XML格式的字符串,然后直接使用该字符串作为存储过程的参数,
    之后整个接口的调整,比如说增加字段等,都不需要再次修改接口的代码,直接修改存储过程即可。

  • 同时还有一个有点:XML类型的元素是可扩展的。若是前端传递的XML中添加了新的元素,这里的解析XML的代码并不会报错。这也是XML的优势之一,就是可以在不中断应用程序的情况下进行扩展。

DECLARE @xml XML;
SET @xml='
<mm_wo_order>
    <id>102457</id>
    <code>BZSC0000001724</code>
    <type>标准生产订单</type>
    <date>2025-01-22 15:47:12</date>
    <factory_code>100</factory_code>
    <quantity></quantity>
    <customer_code></customer_code>
    <create_user>创建者</create_user>
    <create_time>2025-01-20 17:05:37.317</create_time>
    <remark></remark>
    <status>已审核</status>
    <cp_list>
        <cp line_id="102475" item_code="CA000966" quantity="6.0000000000" uom="Pcs" plan_start_date="2025-01-20 00:00:00" so_order_code="XSDD003178" so_order_line="116727">
            <item line_id="160470" item_code="C18010100118" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160471" item_code="C23040200075" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160472" item_code="C18010100062" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160473" item_code="C18010100119" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160474" item_code="C23040200045" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160475" item_code="C13040100007" quantity="30.0000000000" unit_qty="5.000000000000000" uom="G"/>
            <item line_id="160476" item_code="C08070300031" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160477" item_code="C20040100006" quantity="13.0000000000" unit_qty="2.166666666666666" uom="Pcs"/>
            <item line_id="160478" item_code="C02020101527" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160479" item_code="C16020100270" quantity="18.0000000000" unit_qty="3.000000000000000" uom="Pcs"/>
            <item line_id="160480" item_code="C21010200038" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160481" item_code="C20040100030" quantity="55.0000000000" unit_qty="9.166666666666666" uom="Pcs"/>
            <item line_id="160482" item_code="C20040200011" quantity="25.0000000000" unit_qty="4.166666666666666" uom="Pcs"/>
            <item line_id="160483" item_code="C18010100121" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160484" item_code="C23010100101" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160485" item_code="C16040100018" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160486" item_code="C23060200006" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160487" item_code="C08020200128" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160488" item_code="C23040200029" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160489" item_code="C23030200006" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160490" item_code="C18010100134" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160491" item_code="C02020101427" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160492" item_code="C23040200042" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160493" item_code="C23080300008" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160494" item_code="C27020100080" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160495" item_code="C23090100219" quantity="12.0000000000" unit_qty="2.000000000000000" uom="Pcs"/>
            <item line_id="160496" item_code="C20040100031" quantity="13.0000000000" unit_qty="2.166666666666666" uom="Pcs"/>
            <item line_id="160497" item_code="C23080300007" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160498" item_code="C10080100044" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <item line_id="160499" item_code="C27030100371" quantity="6.0000000000" unit_qty="1.000000000000000" uom="Pcs"/>
            <seq line_id="104276" seq_code="10" seq_name="组装" ok_qty="6.0000000000" uom="Pcs" eqp_mpu="10.6830000000" man_mpu="10.6830000000"/>
            <seq line_id="104277" seq_code="20" seq_name="测试" ok_qty="6.0000000000" uom="Pcs" eqp_mpu="23.4830000000" man_mpu="3.7170000000"/>
            <seq line_id="104278" seq_code="30" seq_name="包装" ok_qty="6.0000000000" uom="Pcs" eqp_mpu="1.5830000000" man_mpu="1.5830000000"/>
        </cp>
    </cp_list>
</mm_wo_order>';
--获取工单主表信息
IF OBJECT_ID('tempdb..#tempMa') IS NOT NULL DROP TABLE #tempMa;
SELECT x.value('./id[1]', 'bigint')                  AS Id
      ,x.value('./code[1]', 'nvarchar(50)')          AS Code
      ,x.value('./factory_code[1]', 'nvarchar(50)')  AS Factory_Code
      ,x.value('./customer_code[1]', 'nvarchar(50)') AS Customer_Code
      ,x.value('./type[1]', 'nvarchar(50)')          AS Type
      ,x.value('./date[1]', 'date')                  AS Date
      ,x.value('./create_user[1]', 'nvarchar(50)')   AS Create_User
      ,x.value('./create_time[1]', 'datetime')       AS Create_Time
      ,x.value('./status[1]', 'nvarchar(50)')        AS Status
      ,x.value('./remark[1]', 'nvarchar(500)')       AS Remark
INTO  #tempMa
FROM  @xml.nodes('/mm_wo_order') t(x);
SELECT * FROM #tempMa;
--获取明细表中的item(材料)的主表信息
IF OBJECT_ID('tempdb..#tempCp') IS NOT NULL DROP TABLE #tempCp;
SELECT x.value('@line_id[1]', 'nvarchar(50)')       line_id
      ,x.value('@item_code[1]', 'nvarchar(50)')     item_code
      ,x.value('@quantity[1]', 'decimal(19,6)')     quantity
      ,x.value('@uom[1]', 'nvarchar(50)')           uom
      ,x.value('@plan_start_date[1]', 'date')       plan_start_date
      ,x.value('@so_order_code[1]', 'nvarchar(50)') so_order_code
      ,x.value('@so_order_line[1]', 'nvarchar(50)') so_order_line
INTO  #tempCp
FROM  @xml.nodes('//cp_list/cp') t(x);
SELECT * FROM #tempCp;
--获取明细表中的item的信息
IF OBJECT_ID('tempdb..#tempItem') IS NOT NULL DROP TABLE #tempItem;
SELECT x.value('../@line_id[1]', 'nvarchar(50)') cp_line_id
      ,x.value('@line_id[1]', 'nvarchar(50)')    line_id
      ,x.value('@item_code[1]', 'nvarchar(50)')  item_code
      ,x.value('@quantity[1]', 'decimal(19,6)')  quantity
      ,x.value('@unit_qty[1]', 'decimal(19,6)')  unit_qty
      ,x.value('@close_qty[1]', 'decimal(19,6)') close_qty
      ,x.value('@uom[1]', 'nvarchar(50)')        uom
      ,x.value('@status[1]', 'nvarchar(50)')     status
INTO  #tempItem
FROM  @xml.nodes('//cp_list/cp/item') t(x);
--获取工序的明细表信息
SELECT * FROM #tempItem;
IF OBJECT_ID('tempdb..#tempSeq') IS NOT NULL DROP TABLE #tempSeq;
SELECT x.value('../@line_id[1]', 'nvarchar(50)') cp_line_id
      ,x.value('@line_id[1]', 'nvarchar(50)')    line_id
      ,x.value('@seq_code[1]', 'nvarchar(50)')   seq_code
      ,x.value('@seq_name[1]', 'nvarchar(50)')   seq_name
      ,x.value('@ok_qty[1]', 'decimal(19,6)')    ok_qty
      ,x.value('@ng_qty[1]', 'decimal(19,6)')    ng_qty
      ,x.value('@uom[1]', 'nvarchar(50)')        uom
      ,x.value('@status[1]', 'nvarchar(50)')     status
      ,x.value('@man_mpu[1]', 'decimal(19,6)')   man_mpu
      ,x.value('@eqp_mpu[1]', 'decimal(19,6)')   eqp_mpu
INTO  #tempSeq
FROM  @xml.nodes('//cp_list/cp/seq') t(x);
SELECT * FROM #tempSeq;

  • 结果
| Id     | Code           | Factory_Code | Customer_Code | Type   | Date      | Create_User | Create_Time             | Status | Remark |
| ------ | -------------- | ------------ | ------------- | ------ | --------- | ----------- | ----------------------- | ------ | ------ |
| 102457 | BZSC0000001724 | 100          |               | 标准生产订单 | 2025/1/22 | 创建者         | 2025-01-20 17:05:37.317 | 已审核    |                                                 
                                             

| line_id | item_code | quantity | uom  | plan_start_date | so_order_code | so_order_line |
| ------- | --------- | -------- | ---- | --------------- | ------------- | ------------- |
| 102475  | CA000966  | 6        | Pcs  | 2025/1/20       | XSDD003178    | 116727        |


| cp_line_id | line_id | item_code    | quantity | unit_qty | close_qty | uom  | status |
| ---------- | ------- | ------------ | -------- | -------- | --------- | ---- | ------ |
| 102475     | 160470  | C18010100118 | 6        | 1        |           | Pcs  |        |
| 102475     | 160471  | C23040200075 | 6        | 1        |           | Pcs  |        |
| 102475     | 160472  | C18010100062 | 6        | 1        |           | Pcs  |        |
| 102475     | 160473  | C18010100119 | 6        | 1        |           | Pcs  |        |
| 102475     | 160474  | C23040200045 | 6        | 1        |           | Pcs  |        |
| 102475     | 160475  | C13040100007 | 30       | 5        |           | G    |        |
| 102475     | 160476  | C08070300031 | 6        | 1        |           | Pcs  |        |
| 102475     | 160477  | C20040100006 | 13       | 2.166667 |           | Pcs  |        |
| 102475     | 160478  | C02020101527 | 6        | 1        |           | Pcs  |        |
| 102475     | 160479  | C16020100270 | 18       | 3        |           | Pcs  |        |
| 102475     | 160480  | C21010200038 | 6        | 1        |           | Pcs  |        |
| 102475     | 160481  | C20040100030 | 55       | 9.166667 |           | Pcs  |        |
| 102475     | 160482  | C20040200011 | 25       | 4.166667 |           | Pcs  |        |
| 102475     | 160483  | C18010100121 | 6        | 1        |           | Pcs  |        |
| 102475     | 160484  | C23010100101 | 6        | 1        |           | Pcs  |        |
| 102475     | 160485  | C16040100018 | 6        | 1        |           | Pcs  |        |
| 102475     | 160486  | C23060200006 | 6        | 1        |           | Pcs  |        |
| 102475     | 160487  | C08020200128 | 6        | 1        |           | Pcs  |        |
| 102475     | 160488  | C23040200029 | 6        | 1        |           | Pcs  |        |
| 102475     | 160489  | C23030200006 | 6        | 1        |           | Pcs  |        |
| 102475     | 160490  | C18010100134 | 6        | 1        |           | Pcs  |        |
| 102475     | 160491  | C02020101427 | 6        | 1        |           | Pcs  |        |
| 102475     | 160492  | C23040200042 | 6        | 1        |           | Pcs  |        |
| 102475     | 160493  | C23080300008 | 6        | 1        |           | Pcs  |        |
| 102475     | 160494  | C27020100080 | 6        | 1        |           | Pcs  |        |
| 102475     | 160495  | C23090100219 | 12       | 2        |           | Pcs  |        |
| 102475     | 160496  | C20040100031 | 13       | 2.166667 |           | Pcs  |        |
| 102475     | 160497  | C23080300007 | 6        | 1        |           | Pcs  |        |
| 102475     | 160498  | C10080100044 | 6        | 1        |           | Pcs  |        |
| 102475     | 160499  | C27030100371 | 6        | 1        |           | Pcs  |        |


| cp_line_id | line_id | seq_code | seq_name | ok_qty | ng_qty | uom  | status | man_mpu | eqp_mpu |
| ---------- | ------- | -------- | -------- | ------ | ------ | ---- | ------ | ------- | ------- |
| 102475     | 104276  | 10       | 组装       | 6      |        | Pcs  |        | 10.683  | 10.683  |
| 102475     | 104277  | 20       | 测试       | 6      |        | Pcs  |        | 3.717   | 23.483  |
| 102475     | 104278  | 30       | 包装       | 6      |        | Pcs  |        | 1.583   | 1.583   |

6.参考

posted @   shanzm  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2020-02-11 .NET异步程序设计——异步委托
2019-02-11 《SQL CookBook 》笔记-第二章-查询结果排序
TOP
点击右上角即可分享
微信分享提示