C#/ODP.NET:大 IN 子句解决方法

2024-02-19

我们有一个 C# 组件,可以处理将任意大小的元素列表附加到半任意 SQL 的 IN 子句中SELECT查询。本质上这可以归结为接收类似的东西:

SELECT COUNT(*) FROM a WHERE b IN (...)

...其中“...”是允许组件修改的查询的唯一部分。

目前,该组件将插入一组以逗号分隔的命名绑定参数,然后将相应的 IDbDataParameter 对象附加到命令并执行;组件知道它必须绑定的参数的类型。这种方法效果很好,直到调用代码提供的参数集大于数据库愿意接受的参数集为止。这里的目标是让如此大的集合通过 ODP.NET 对 Oracle 11gR2 进行查询。

这项任务有些复杂,因为以下方法被制定要求的人认为是不可接受的:

  • 全局临时表
  • 存储过程
  • 任何需要的东西CREATE TYPE已被处决

解决这一问题的方法并不需要只执行一个查询。

我试图通过使用来自其他地方的代码将子句绑定为数组来完成这项工作:

IList<string> values;

//...

OracleParameter parameter = new OracleParameter();
parameter.ParameterName = "parm";
parameter.DbType = DbType.String;
parameter.Value = values.ToArray();
int[] sizes = new int[values.Count];
for (int index = 0; index < values.Count; index++)
{
    sizes[index] = values[index].Length;
}
parameter.ArrayBindSize = sizes;

//...

该命令随后执行,不会引发异常,但 COUNT 返回的值为零(与预期值相比,在 SQLDeveloper 中使用嵌套的查询运行)SELECT返回相同的参数集)。到目前为止,浏览 ODP.NET 文档并没有带来任何乐趣。

对此的问题是:

  • 有没有办法让上面的参数附件按预期工作?
  • 是否有另一种可行的方法可以在不使用被否决的方法之一的情况下实现这一目标?

(我知道这类似于这个(未回答的)问题 https://stackoverflow.com/questions/21412243/passing-list-of-numbers-as-parameter-to-managed-odp-net-from-c-sharp,但该场景没有提到对方法有相同的限制。)


好吧,既然不允许使用全局临时表,那么至少可以创建普通表吗?如果是这样,这里有一个方法:

使用以下命令文本创建 OracleCommand 对象:

@"BEGIN
CREATE TABLE {inListTableName}
(
  inValue   {dbDataType}
)

INSERT INTO {inListTableName}(inValue) VALUES(:inValue);
END"

将命令对象上的 ArrayBindCount 设置为列表中所需的项目数。

Replace {inListTableName}Guid.NewGuid().ToString().

更换{dbDataType}使用正确的 Oracle 数据类型来表示要在 in 子句中使用的值列表。

将 OracleParameter 添加到名为“inValue”的 OracleCommand 中,并将参数的值设置为包含 in 子句中所需值的数组。如果您有哈希集(我建议使用它以避免发送不必要的重复项),请使用.ToArray()就可以得到一个数组。

执行这个命令。这是您的准备命令。

然后使用以下 sql 片段作为 select sql 语句中 in 子句的值部分:(SELECT {inListTableName}.inValue FROM {inListTableName})

例如:

SELECT FirstName, LastName FROM Users WHERE UserId IN (SELECT {inListTableName}.inValue FROM {inListTableName});

执行此命令以获取读取器。

最后,还有一个命令,其命令文本如下:

DROP TABLE {inListTableName};

这是您的清理命令。执行这个命令。

您可能想要创建一个备用架构/用户来创建inListTable这样您就可以向用户授予适当的权限,使其仅在该架构中创建表。

所有这些都可以封装在具有以下接口的可重用类中:

public interface IInListOperation
{
    void    TransmitValueList(OracleConnection connection);
    string  GetInListSQLSnippet();
    void    RemoveValueList();
}

TransmitValueList将创建您的准备命令,添加参数并执行准备命令。

GetInListSQLSnippet只会返回(SELECT {inListTableName}.inValue FROM {inListTableName});

RemoveValueList清理干净。

该类的构造函数将采用值列表和 oracle db 数据类型,并生成inListTableName.

如果您可以使用全局临时表,我建议您不要创建和删除表。

编辑: 我想补充一点,如果您的条款涉及NOT IN列表或其他不等式运算符。以下面为例:

SELECT FirstName, LastName FROM Users WHERE Status == 'ACTIVE' OR UserID NOT IN (1,2,3,4,5,6,7,8,9,10);

如果使用拆分的方法NOT IN分开,你最终会得到无效的结果。以下对上一个示例进行划分的示例将返回所有用户,而不是除 UserId 1-10 之外的所有用户。

SELECT FirstName, LastName FROM Users WHERE UserID NOT IN (1,2,3,4,5)
UNION
SELECT FirstName, LastName FROM Users WHERE UserID NOT IN (6,7,8,9,10);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#/ODP.NET:大 IN 子句解决方法 的相关文章

随机推荐

  • 无内存屏障的乱序写入:数据争用的唯一可能原因?

    在经历的同时Java 并发实践 作者 Brian Goetz我遇到了以下行 当一个变量被多个线程读取时 就会发生数据竞争 并由至少一个线程写入 但读取和写入不是按发生之前排序 正确同步的程序之一是 没有数据竞争 正确同步的程序表现出顺序 一
  • 这是 Xamarin Forms 中的内存泄漏吗?

    我遇到了一个问题 页面对象一旦被导航离开 就不会被垃圾收集 我整理了一个非常基本的示例 演示了使用 NavigationPage 和 PushAsync 方法时出现的问题 该页面使用弱引用列表显示 活动 页面的数量 public class
  • tar:错误不可恢复:现在退出

    当我解开教义时 rw r r 1 root root 660252 2010 10 16 23 06 Doctrine 1 2 0 tgz 我总是收到此错误消息 root X100e usr local lib Doctrine stabl
  • 何时在带有react-dom的jest单元测试中使用act()

    根据反应单元测试文档 act 要为断言准备组件 请包装代码渲染 它并在 act 调用中执行更新 这使得你的测试 运行起来更接近 React 在浏览器中的工作方式 但测试在这两种情况下都运行得很好 没有 act it Should retur
  • Linux堆栈的动态扩展

    我注意到 Linux 堆栈开始时很小 然后由于递归 推送 vlas 达到大小而导致页面错误而扩展getrlimit RLIMIT STACK 给予或接受 在我的系统上默认为 8MiB 但奇怪的是 如果我通过直接寻址字节来导致页面错误 在限制
  • 如何将 Web 服务绑定到特定 glassfish 端口?

    I have Glassfish 3 1 1 Metro JAX WS stack 在我的域的虚拟服务器中安装多个 http 侦听器 当我部署 EAR 时 Web 应用程序和肥皂服务都绑定到所有可用的 http 侦听器 而我希望它们由不同的
  • Gas .org 与 nasm 中的 ORG 不同吗?

    我使用 gnu 作为简单的启动 是这样的 text org 0x7c00 start movw 0x7c0 ax movw ax ds movw ax es leaw greeting msg si call prtstr end fill
  • Task.Result 与 .GetAwaiter.GetResult() 相同吗?

    我最近正在阅读一些使用大量异步方法的代码 但有时需要同步执行它们 该代码的作用是 Foo foo GetFooAsync GetAwaiter GetResult 这是否与 Foo foo GetFooAsync Result Task G
  • 通过 ADB 更改设备语言

    我想通过 ADB 更改语言 我尝试 adb shell setprop persist sys language fr setprop persist sys country CA stop sleep 5 start 但我收到错误 set
  • 如何在 Node js 中使用 module.exports 导出数组?

    我有一个使用node js 的项目 这是我第一次使用nodejs 我想将数组导出到我的应用程序 这是一些代码 module exports var arrays arrays 0 array 0 arrays 1 array 1 array
  • 为什么 easeljs stage.getBounds() 返回 null?

    在这个例子中 var canvas document getElementById testCanvas var stage new createjs Stage canvas function drawRectangle var rect
  • 当我们在键盘上键入时,如何使字符串的内容显示在屏幕上?

    我有这个功能 玩家可以输入他的名字 但我希望每个字母在他输入时出现在屏幕上 这是我的功能 def input player name player name screen True name win blit player name bg
  • Spring Security,安全访问和非安全访问

    我正在做一个需要先登录的小应用程序 但对于某些第三方工具 我想提供一个不需要登录的API 登录本身工作正常 API 本身工作正常 但我不知道如何告诉 Spring Security 无需身份验证即可访问 API 我在这里和其他网站上检查了几
  • Spring mvc 验证异常处理程序在控制器方法之前调用

    我有以下代码 public class StudentController extends BaseController RequestMapping value student edit method RequestMethod POST
  • Flask-Sqlalchemy:数据库查询不返回新数据

    我正在构建一个应用程序 它从一项服务接收 webhook 将数据存储在数据库中 然后通过 API 提供数据 我能够成功地将数据添加到我的应用程序中 但是当我查询数据库时 我只收到上次启动应用程序时数据库中的第一次提交 例如 如果我启动应用程
  • Android:ListView 中的按钮未接收 onClick 事件

    我正在制作一个日期选择器活动 看起来像滚动的 30 天月份 日历 想想 Outlook 日历 日期选择器包含 MonthView 视图的 ListView 用于滚动 每个视图都是各个日期的 TableView MonthView 中的每一天
  • FPGA 有哪些实际应用?

    我对我的程序为一个小型七段显示器提供动力感到非常兴奋 但是当我向不在现场的人展示它时 他们总是说 那么你能用它做什么 我永远无法给他们一个简洁的答案 谁能帮我吗 第一 它们不需要具有易失性存储器 事实上 大厂商 Xilinx Altera
  • 如何从输出迭代器获取值类型?

    假设我有一个 C 容器 例如 MyContainer 包含的对象存储为void 指针 迭代此容器元素的唯一方法是通过两个接口函数 getFirstElem MyContainer const void 输出容器的第一个元素 getNextE
  • 为什么组件中的 React Native 函数没有“function”关键字?

    在 javascript 函数中声明为function myFuncName 但 React React Native 函数省略了该关键字 这是 ES6 JSX 或 React 特有的吗 这是ES6的一个特性 更多信息请访问https ba
  • C#/ODP.NET:大 IN 子句解决方法

    我们有一个 C 组件 可以处理将任意大小的元素列表附加到半任意 SQL 的 IN 子句中SELECT查询 本质上这可以归结为接收类似的东西 SELECT COUNT FROM a WHERE b IN 其中 是允许组件修改的查询的唯一部分