如何给SQLSERVER存储过程传递数组参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何给SQLSERVER存储过程传递数组参数相关的知识,希望对你有一定的参考价值。

参考技术A 数组不能传递,变通的解决办法是有的
思路如下:
1、将数组转换为字符串格式(例如:a,b,c,d)
2、在数据库内创建字符串分割为行的表值函数
3、若是需要将一个二维数组传递的话,需要将每列数据都格式化为1的方式,然后再用2的方式转换为行,再将转换后的数据组合为一个表
4、你就可以直接进行插入、编辑、删除或查询操作了。

将字节数组传递给 oracle 存储过程

【中文标题】将字节数组传递给 oracle 存储过程【英文标题】:Pass a byte array to oracle stored procedure 【发布时间】:2014-04-24 11:11:56 【问题描述】:

我在使用 odp.net 将字节数组作为输入参数传递给 Oracle 存储过程时遇到了一个问题。

这里是存储过程签名:

SOMEPROCEDURE(session IN NUMBER, data IN RAW)

这里是C#代码,调用过程:

var cmd = new OracleCommand("SOME_PROCEDURE", _connection);
cmd.CommandType = CommandType.StoredProcedure;
var bt = new byte[]1,68,0,83,128,1;
OracleParameter sessionId = new OracleParameter("dbSessionId", OracleDbType.Decimal, new OracleDecimal(_dbSessionId), ParameterDirection.Input);                
OracleParameter data = new OracleParameter("statusData", OracleDbType.Raw, new OracleBinary(bt), ParameterDirection.Input);
cmd.Parameters.Add(sessionId);
cmd.Parameters.Add(data);
cmd.ExecuteNonQuery();

此代码失败(存储过程抛出异常,无法获取数据),因为字节数组中有数字128!,如果我在另一个数字上chage 128,减去128,它可以正常工作!

我该怎么办?

【问题讨论】:

【参考方案1】:

试试这个:

var cmd = new OracleCommand("SOME_PROCEDURE", _connection);
cmd.CommandType = CommandType.StoredProcedure;
int[] bt = new int[]1,68,0,83,128,1;
OracleParameter sessionId = new OracleParameter("dbSessionId", OracleDbType.Decimal, new OracleDecimal(_dbSessionId), ParameterDirection.Input);                
OracleParameter data = new OracleParameter("statusData", OracleDbType.Raw, new OracleBinary(bt), ParameterDirection.Input);
cmd.Parameters.Add(sessionId);
cmd.Parameters.Add(data);
cmd.ExecuteNonQuery();

这可能是因为一个字节太小,一个 int 可能会起作用,因为它可能包含一个更大的数字。

【讨论】:

没有OracleBinary构造函数将Int32数组作为参数,也没有从byte数组到int数组的隐式对话。 我不知道,您可以尝试制作 2 个字节数组。 字节不小,字节是8位无符号整数,所以它的最大值是255。看来,oracle数据行不能包含无符号8位值。【参考方案2】:

经过一些实验,我找到了解决方案。 首先,如果该数组包含大于 127 的值,则不能通过 odp.net 传递给存储过程的字节数组。

所以,解决方案: 1. 创建包装程序

procedure SOME_PROCEDURE_WRAPPER (p_session_id in number,
                                  p_data       in varchar2)
is
 v_data  raw(1024);
 rawdata  raw(1024);
 rawlen number;
 hex varchar2(32760);
 i number;    
 begin  

  rawlen := length(p_data);
  i := 1;
  while i <= rawlen-1 
  loop
     hex := substrb(p_data,i,2);
     rawdata := rawdata || HEXTORAW(hex);
     i := i + 2;
  end loop;  
  SOME_PROCEDURE(p_session_id , rawdata);
 end;

2 然后需要这样修改C#代码:

 var cmd = new OracleCommand("SOME_PROCEDURE_WRAPPER", _connection);
 cmd.CommandType = CommandType.StoredProcedure;
 string @string = statusData.ToHexString();
 OracleParameter sessionId = new OracleParameter("dbSessionId", OracleDbType.Decimal, new OracleDecimal(_dbSessionId), ParameterDirection.Input);                
 OracleParameter data = new OracleParameter("statusData", OracleDbType.Varchar2,@string.Length, new OracleString(@string), ParameterDirection.Input);
 cmd.Parameters.Add(sessionId);
 cmd.Parameters.Add(data);
 cmd.ExecuteNonQuery();

在哪里

public static string ToHexString(this byte[] bytes)
     
        if(bytes == null || bytes.Length == null)
            return string.Empty;
        StringBuilder hexStringBuilder = new StringBuilder();
        foreach (byte @byte in bytes)
        
            hexStringBuilder.Append(@byte.ToString("X2"));
        
        return hexStringBuilder.ToString();
    

【讨论】:

以上是关于如何给SQLSERVER存储过程传递数组参数的主要内容,如果未能解决你的问题,请参考以下文章

VBA ADO 将数组参数传递给存储过程

Sql server2012存储过程参数传递null值,如何判定这个参数是null

如何使用 JDBC 将表值参数(类数组参数)传递给 Microsoft SQL Server 2008 R2 中的存储过程? [复制]

如何使用 ADO 和 VB 将 NULL 或空字符串传递给存储过程输入参数?

如何将 .NET 对象集合(父子)层次结构传递给 SQL Server 存储过程

Sqlserver中存储过程,触发器,自定义函数