You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PL/SQL存储过程中扩展INTERSECT实现多商品交集查询

解决可变数量商品的门店查询需求

1. 定义数据库集合类型

首先需要在Oracle中创建一个可接收批量数字参数的集合类型,用于对接C#传入的List<int>:

CREATE OR REPLACE TYPE NUMBER_LIST AS TABLE OF NUMBER;
/

2. 编写支持可变参数的PL/SQL存储过程

无需嵌套多轮INTERSECT,用分组统计+条件筛选的方式更高效简洁:

CREATE OR REPLACE PROCEDURE FindStoresSellingAllItems(
    p_items IN NUMBER_LIST,
    p_result OUT SYS_REFCURSOR
) AS
BEGIN
    OPEN p_result FOR
        SELECT StoreId
        FROM StockItem
        WHERE ItemId MEMBER OF p_items
        GROUP BY StoreId
        HAVING COUNT(DISTINCT ItemId) = CARDINALITY(p_items);
END;
/
  • 逻辑说明:先筛选出包含传入商品列表中任一商品的门店记录,按门店分组后,统计该门店匹配到的不同商品数量;当数量等于传入商品的总数时,说明该门店拥有所有指定商品。
  • 使用SYS_REFCURSOR作为输出参数,方便C#接收查询结果。

3. C#调用示例

对应方法实现如下(需使用Oracle官方数据访问组件Oracle.ManagedDataAccess.Client):

using Oracle.ManagedDataAccess.Client;
using System.Collections.Generic;
using System.Data;

public List<int> FindStoresSellingAllItems(List<int> items)
{
    var storeIds = new List<int>();
    string connString = "你的Oracle数据库连接字符串";

    using (var conn = new OracleConnection(connString))
    {
        conn.Open();
        using (var cmd = new OracleCommand("FindStoresSellingAllItems", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;

            // 传入商品列表参数
            var itemsParam = new OracleParameter("p_items", OracleDbType.Array)
            {
                Direction = ParameterDirection.Input,
                UdtTypeName = "NUMBER_LIST",
                Value = items.ToArray()
            };

            // 输出结果游标参数
            var resultParam = new OracleParameter("p_result", OracleDbType.RefCursor)
            {
                Direction = ParameterDirection.Output
            };

            cmd.Parameters.Add(itemsParam);
            cmd.Parameters.Add(resultParam);

            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    storeIds.Add(reader.GetInt32(0));
                }
            }
        }
    }
    return storeIds;
}

补充说明

如果不想用集合类型,也可以通过动态SQL拼接多轮INTERSECT,但这种方式存在SQL注入风险,且性能远不如分组统计方案,因此更推荐上述集合+分组的实现方式。

内容的提问来源于stack exchange,提问作者Mr. Boy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:35:33