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
- 从上次统计数据为 运行.
我的代码正在运行,该函数为我提供了正确的 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
- 从上次统计数据为 运行.