我需要使用从Oracle数据库检索到的数据来提供我的Octave实例。
我已经在我的Octave实例中实现了OJDBC连接,现在我能够将来自Oracle数据库的数据放入Octave中的Java ResultSet对象中(取自:https://lists.gnu.org/archive/html/help-octave/2011-08/msg00250.html):
javaaddpath('access-path-to-ojdbc8.jar') ;
props = javaObject('java.util.Properties') ;
props.setProperty("user", 'username') ;
props.setProperty("password", 'password') ;
driver = javaObject('oracle.jdbc.OracleDriver') ;
url = 'jdbc:oracle:thin:@ip:port:schema' ;
con = driver.connect(url, props) ;
sql = 'select-query' ;
ps = con.prepareStatement(sql) ;
rs = ps.executeQuery() ;
但是尚未成功从该ResultSet检索数据。
如何将Octave中ResultSet对象中的数据放入数组或矩阵中?
答案 0 :(得分:0)
我无权访问指定的.jar或合适的数据库来测试您的特定代码,但是在任何情况下,这实际上都不是八度的问题。实际上,您需要ResultSet类的相关api,以及用于处理它的标准方法。甲骨文documentation建议您在Java中执行以下操作:
while (rs.next()) { System.out.println (rs.getString(1)); }
因此,大概也是通过octave进行的操作,除了通过octave的java接口。
while rs.next().booleanValue % since a Boolean java object by itself
% isn't valid logical input for octave's
% 'while' statement
% do something with rs, e.g. fill in a cell array
endwhile
据我所知,关于是否可以将java数组自动转换为八度单元格对象,反之亦然。就像在Java中一样,您必须通过for循环设置/获取元素之间的元素(例如,参见手册中有关javaArray函数的注释)
答案 1 :(得分:0)
您需要ResultSet
和相关类的文档在Java JDBC API documentation中。 (除非您想做一些特定于Oracle的东西,否则您不需要Oracle特定的doco。所有JDBC驱动程序都符合通用的JDBC API。)因为它是一个Java对象,所以您将使用与Java代码相同的Octave方法调用。
要转换为八度值,请知道Java原语会自动转换为八度类型,java.lang.String
对象需要通过对它们调用char(...)
来进行转换,而java.sql.Date
值则必须转换为手动datenums
。 (懒惰的方法是获取它们的字符串值并对其进行解析;快速的方法是获取其Unix时间值并进行数字转换。)
由于Java JDBC一次使结果集游标前进一行,并且需要单独的方法调用来获取每一列的值,因此需要使用一对嵌套循环来遍历ResultSet。像这样:
rsMeta = rs.getMetaData();
nCols = rsMeta.getColumnCount();
data = NaN(1, nCols);
iRow = 0;
while rs.next()
iRow = iRow + 1;
for iCol = 1:nCols
data(iRow,iCol) = rs.getDouble(iCol);
endfor
endwhile
啊,但是如果您的栏位不是全部数字怎么办?然后,您需要查看rsMeta
中的列类型,将其打开,并使用单元格数组来保存异构数据集。像这样:
rsMeta = rs.getMetaData();
nCols = rsMeta.getColumnCount();
data = cell(1, nCols);
iRow = 0;
while rs.next()
iRow = iRow + 1;
for iCol = 1:nCols
colTypeId = rsMeta.getColumnType(iCol);
switch colTypeId
case NUMERIC_TYPE
data{iRow,iCol} = rs.getDouble(iCol);
case CHAR_TYPE
data{iRow,iCol} = rs.getString(iCol);
data{iRow,iCol} = char(data{iRow,iCol});
# ... and so on ...
otherwise
error('Unsupported SQL data type in column %d: %d', ...
iCol, colTypeId);
endswitch
endfor
endwhile
您如何知道NUMERIC_TYPE
,CHAR_TYPE
等的值是什么?您必须检查java.sql.Types
Java类中的值。在运行时执行此操作,以确保与要运行的JDK保持一致。
(注意:这段代码是简单,草率的方法。您可以(并且应该)对其进行各种改进和优化。)
不幸的是,这样做的性能会浪费很多时间,因为从Octave调用Java方法非常昂贵,并且单元存储数据的效率很低。如果结果集很大,为了获得良好的性能,您需要做的是在Java中编写一个结果集缓冲层 ,该层在Java中运行循环并将结果按原始的每个列进行缓冲数组,并使用它。如果您想了解如何执行此操作的示例,请使用an example implementation in Matlab in my Janklab library(M代码层here)。随时窃取代码。 Octave不支持Java构造函数或类方法的点引用,因此要将其转换为Octave,您需要将所有那些替换为javaObject
和javaMethod
调用。 (这很乏味,并且代码很丑陋,所以我自己不会做。很抱歉。)
如果您不愿意这样做(并且确实是谁?),并且仍然需要良好的性能,那么实际上您应该做的就是忘记将Octave直接连接到Oracle并编写一个单独的Python / NumPy或R程序接收您的查询,对您的Oracle数据库运行查询,并将结果写入.mat
文件,然后从Octave读取该文件。