cmd.executescalar() 有效但抛出 ORA-25191 异常

cmd.executescalar() works but throws ORA-25191 Exception

我的代码正在运行,该函数为我提供了正确的 Select 计数 (*) 值,但无论如何,它抛出一个 ORA-25191 异常 - 无法引用索引组织的溢出 table table 提示, 在 retVal = Convert.ToInt32(cmd.ExecuteScalar());

由于我经常使用该函数,异常会极大地降低我的程序速度。

 private int getSelectCountQueryOracle(string Sqlquery)
        {
            try
            {
                int retVal = 0;
                using (DataTable dataCount = new DataTable())
                {
                    using (OracleCommand cmd = new OracleCommand(Sqlquery))
                    {
                        cmd.CommandType = CommandType.Text;
                        cmd.Connection = oraCon;

                        using (OracleDataAdapter dataAdapter = new OracleDataAdapter())
                        {
                            retVal = Convert.ToInt32(cmd.ExecuteScalar());
                        }
                    }
                }
                return retVal;
            } 
            catch (Exception ex)
            {
                exceptionProtocol("Count Function", ex.ToString());
                return 1;
            }
        }

此函数在 foreach 循环中调用

    // function call in foreach loop which goes through tablenames
        foreach (DataRow row in dataTbl.Rows)
                    {...    
                     tableNameFromRow = row["TABLE_NAME"].ToString();                                 
                     tableRows=getSelectCountQueryOracle("select count(*) as 'count' from " +tableNameFromRow);
                     tableColumns = getSelectCountQueryOracle("SELECT COUNT(*) as 'count' FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='" + tableNameFromRow + "'");
                     ...}

dataTbl.rows在这个外层循环中,反过来来自query

SELECT * FROM USER_TABLES ORDER BY TABLE_NAME

article 帮助我解决了我的问题。

我已将查询更改为:

SELECT * FROM user_tables 
WHERE iot_type IS NULL OR iot_type != 'IOT_OVERFLOW' 
ORDER BY TABLE_NAME

如果您使用的是与数据库无关的 API,例如 ADO.Net,您几乎总是希望使用 API 的框架来获取元数据,而不是编写自定义查询针对每个数据库的元数据 tables。各种 ADO.Net 提供商更有可能编写处理所有各种极端情况的数据字典查询,并且比您可能编写的查询更有可能得到优化。因此,与其编写自己的查询来填充 dataTbl 数据 table,不如使用 GetSchema 方法

DataTable dataTbl = connection.GetSchema("Tables");  

如果您出于某种原因想要保留自定义编码的数据字典查询,则需要过滤掉 IOT 溢出 table,因为您无法直接查询它们。

select *
  from user_tables
 where iot_type IS NULL
    or iot_type != 'IOT_OVERFLOW'

但是请注意,您可能不想尝试从其他 table 中获取计数。例如,dropped 列表示 table 是否已被删除——可能是您不想计算回收站中某个对象的行数。因此,您还需要一个 dropped = 'NO' 谓词。而且你不能在嵌套的 table 上执行 count(*),所以如果你的模式恰好包含嵌套的 table,你也想有一个 nested = 'NO' 谓词。可能还有其他极端情况,具体取决于您的特定模式使用的确切功能集,提供程序的开发人员已经为您必须处理的代码添加了代码。

所以我会从

开始
select *
  from user_tables
 where (   iot_type IS NULL
        or iot_type != 'IOT_OVERFLOW')
   and dropped = 'NO'
   and nested = 'NO'

但要知道您可能需要/想要添加一些额外的过滤器,具体取决于用户使用的特定功能。我当然宁愿让开发 ADO.Net 提供程序的优秀人员担心所有这些极端情况,也不愿自己处理所有这些情况。

不过,退后一步,我会质疑为什么您经常对模式中的每个 table 执行 count(*),以及为什么您需要一个确切的答案。在大多数情况下,当您进行计数时,您要么是在不太关心需要多长时间(即迁移后的验证步骤)或近似计数就足够了(即获取列表)系统中最大的 tables 以便对一些工作进行分类或跟踪随时间的增长以进行预测)在这种情况下,您可以只使用已经存储在数据字典中的计数 - user_tables.num_rows - 从上次统计数据为 运行.