Gar*_*eth 7 c# sql oracle parameters oracle10g
得到了我需要修改的#.net应用程序.此刻的查询有效地做到了这一点:
select * from contract where contractnum = :ContractNum
Run Code Online (Sandbox Code Playgroud)
(非常简化,只是为了表明我们正在使用=和一个参数)
该参数从C#app上的Settings.Settings文件中读取,并且其中包含一个字符串.我需要修改它以包含多个合同,所以我想我可以将SQL更改为:
select * from contract where contractnum in (:ContractNum)
Run Code Online (Sandbox Code Playgroud)
但无论我如何格式化参数中的字符串,都不会返回任何结果.
有没有办法让oracle用参数做一个IN?
任何帮助表示感谢,谢谢大家.
当您使用ODP.NET作为数据提供者时,可以使用Oracle数字集合作为参数(绑定变量).这适用于Oracle服务器9,10或11以及ODP.net版本> = 11.1.0.6.20.
当您使用适用于Oracle的Devart的.NET数据提供程序时,可以使用类似的解决方案.
让我们选择contractnum 3和4的合同.
我们必须使用Oracle类型将一组合同号转移到我们的查询中.
MDSYS.SDO_ELEM_INFO_ARRAY因为如果我们使用这个已经预定义的Oracle类型,我们就不必定义我们自己的Oracle类型.您最多可以填写MDSYS.SDO_ELEM_INFO_ARRAY1048576个号码.
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果省略提示/*+基数(选项卡10)*/,则不使用contract.contractnum上的索引.我假设contractnum是主键,因此该列将被索引.
另见:http : //forums.oracle.com/forums/thread.jspa?messageID=3869879#3869879
您可以使用流水线函数将字符串转换为可与IN操作员一起使用的表.例如(使用10gR2测试):
SQL> select * from table(demo_pkg.string_to_tab('i,j,k'));
COLUMN_VALUE
-----------------
i
j
k
Run Code Online (Sandbox Code Playgroud)
使用以下包:
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
Run Code Online (Sandbox Code Playgroud)
您的查询将如下所示:
select *
from contract
where contractnum in (select column_value
from table(demo_pkg.string_to_tab(:ContractNum)))
Run Code Online (Sandbox Code Playgroud)
尚未找到一个支持评估包含逗号作为唯一IN子句分隔的单个字符串变量的数据库。
您的选择是对变量进行子字符串化,以便逗号分隔的变量内容转换为行,这样您就可以加入到此变量中。或者使用动态 SQL,这是在执行语句之前在存储过程中构造为字符串的 SQL 语句。