有一个C#.net应用程序中,我需要修改。 目前该查询有效地做到这一点:
select * from contract where contractnum = :ContractNum
(非常简单,只是为了显示我们正在使用=和一个参数)
该参数读取从Settings.Settings在C#应用程序文件,并在其一个字符串。 我需要修改它包括多个合同,所以我想我可以改变SQL语句:
select * from contract where contractnum in (:ContractNum)
但不返回任何结果,无论我如何格式化参数字符串。
有没有一种方法可以让我得到神谕做一个与参数?
任何帮助表示赞赏,感谢所有。
还没有找到支持评估包含逗号分隔作为唯一一个字符串变量分贝IN
子句。
你的选择是子字符串变量,以便以逗号分隔的变量内容都变成了行,这样,那么你可以加入到这一点。 或者使用动态SQL,则执行语句前是作为一个字符串在一个存储过程构造SQL语句。
您可以使用管道函数将一个字符串转换成可与使用表IN
操作符。 例如(具有10gR2中测试):
SQL> select * from table(demo_pkg.string_to_tab('i,j,k'));
COLUMN_VALUE
-----------------
i
j
k
用下面的包:
SQL> CREATE OR REPLACE PACKAGE demo_pkg IS
2 TYPE varchar_tab IS TABLE OF VARCHAR2(4000);
3 FUNCTION string_to_tab(p_string VARCHAR2,
4 p_delimiter VARCHAR2 DEFAULT ',')
5 RETURN varchar_tab PIPELINED;
6 END demo_pkg;
7 /
Package created
SQL> CREATE OR REPLACE PACKAGE BODY demo_pkg IS
2 FUNCTION string_to_tab(p_string VARCHAR2,
3 p_delimiter VARCHAR2 DEFAULT ',')
4 RETURN varchar_tab PIPELINED IS
5 l_string VARCHAR2(4000) := p_string;
6 l_first_delimiter NUMBER := instr(p_string, p_delimiter);
7 BEGIN
8 LOOP
9 IF nvl(l_first_delimiter,0) = 0 THEN
10 PIPE ROW(l_string);
11 RETURN;
12 END IF;
13 PIPE ROW(substr(l_string, 1, l_first_delimiter - 1));
14 l_string := substr(l_string, l_first_delimiter + 1);
15 l_first_delimiter := instr(l_string, p_delimiter);
16 END LOOP;
17 END;
18 END demo_pkg;
19 /
Package body created
您的查询应该是这样的:
select *
from contract
where contractnum in (select column_value
from table(demo_pkg.string_to_tab(:ContractNum)))
您可以使用数字的一个Oracle集合作为一个参数(绑定变量)当您使用ODP.NET为数据提供器。 这适用于Oracle服务器9,10或11和ODP.net释放> = 11.1.0.6.20。
当您使用Devart的用于Oracle .NET数据提供程序类似的解决方案是可能的。
我们选择与contractnum的3和4的合约。
我们使用Oracle类型合同的数字阵列转移到我们的查询。
MDSYS.SDO_ELEM_INFO_ARRAY
的使用,因为如果我们采用这种已经可以预定义的Oracle类型,我们没有定义我们自己的Oracle类型。 您可以填写MDSYS.SDO_ELEM_INFO_ARRAY
,最大1048576号。
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
[OracleCustomTypeMappingAttribute("MDSYS.SDO_ELEM_INFO_ARRAY")]
public class NumberArrayFactory : IOracleArrayTypeFactory
{
public Array CreateArray(int numElems)
{
return new Decimal[numElems];
}
public Array CreateStatusArray(int numElems)
{
return null;
}
}
private void Test()
{
OracleConnectionStringBuilder b = new OracleConnectionStringBuilder();
b.UserID = "sna";
b.Password = "sna";
b.DataSource = "ora11";
using (OracleConnection conn = new OracleConnection(b.ToString()))
{
conn.Open();
using (OracleCommand comm = conn.CreateCommand())
{
comm.CommandText =
@" select /*+ cardinality(tab 10) */ c.* " +
@" from contract c, table(:1) tab " +
@" where c.contractnum = tab.column_value";
OracleParameter p = new OracleParameter();
p.OracleDbType = OracleDbType.Array;
p.Direction = ParameterDirection.Input;
p.UdtTypeName = "MDSYS.SDO_ELEM_INFO_ARRAY";
//select contract 3 and 4
p.Value = new Decimal[] { 3, 4 };
comm.Parameters.Add(p);
int numContracts = 0;
using (OracleDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
numContracts++;
}
}
conn.Close();
}
}
}
当一个省略的提示/ * +基数(标签10)* /不使用上contract.contractnum索引。 我以为contractnum是主键,以便本栏目将被编入索引。
在此还看到: http://forums.oracle.com/forums/thread.jspa?messageID=3869879#3869879
对于使用参数中陈述,你可以使用这样的结构:
select * from contract where contractnum
in (select column_value from table (:ContractNum))
其中ContractNum是自定义数组类型。