云服务器内容精选

  • 创建和调用存储过程(入参为复合数据类型) 以下用例展示A兼容模式下,入参为复合数据类型的存储过程创建和调用情况。前置条件是数据库建连完成、连接对象为conn。 创建存储过程test_proc示例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // 在数据库创建复合数据类型。 CREATE TYPE compfoo AS (f1 int, f3 text); // 在数据库中创建table类型。 create type compfoo_table is table of compfoo; // 在数据库中创建如下存储过程,它带有out参数。 create or replace procedure test_proc ( psv_in in compfoo, table_in in compfoo_table, psv_out out compfoo, table_out out compfoo_table ) as begin psv_out := psv_in; table_out:=compfoo_table(); table_out.extend(table_in.count); for i in 1..table_in.count loop table_out(i):=table_in(i); end loop; end; / 调用存储过程test_proc步骤如下: 设置参数behavior_compat_options='proc_outparam_override'后,调用Connection的prepareCall方法创建调用语句对象cs。 1 2 3 Statement statement = conn.createStatement(); statement.execute("SET behavior_compat_options='proc_outparam_override'"); CallableStatement cs = conn.prepareCall("{ CALL test_proc(?,?,?,?) }"); 调用CallableStatement的set方法设置参数。 1 2 3 4 5 6 7 8 PGobject pGobject = new PGobject(); pGobject.setType("public.compfoo"); // 设置复合类型名,格式为“schema.typename”。 pGobject.setValue("(1,demo)"); // 绑定复合类型值,格式为“(value1,value2)”。 cs.setObject(1, pGobject); pGobject = new PGobject(); pGobject.setType("public.compfoo_table"); // 设置Table类型名,格式为"schema.typename"。 pGobject.setValue("{\"(10,demo10)\",\"(11,demo111)\"}"); // 绑定Table类型值,格式为"{\"(value1,value2)\",\"(value1,value2)\",...}"。 cs.setObject(2, pGobject); 调用CallableStatement的registerOutParameter方法注册输出参数。 1 2 3 4 // 注册out类型的参数,类型为复合类型,格式为“schema.typename”。 cs.registerOutParameter(3, Types.STRUCT, "public.compfoo"); // 注册out类型的参数,类型为Table类型,格式为“schema.typename”。 cs.registerOutParameter(4, Types.ARRAY, "public.compfoo_table"); 调用CallableStatement的execute方法执行SQL语句。 1 cs.execute(); 调用CallableStatement的getObject方法获取输出参数。 1 2 3 4 5 6 7 8 9 10 11 12 // 返回结构是自定义类型。 PGobject result = (PGobject)cs.getObject(3); // 获取out参数。 result.getValue(); // 获取复合类型字符串形式值。 result.getArrayValue(); // 获取复合类型数组形式值,以复合数据类型字段顺序排序。 result.getStruct(); // 获取复合类型子类型名,按创建顺序排序。 result.getAttributes(); // 返回自定义类型每列组成类型的对象,对于array类型和table类型返回的是PgArray,对于自定义类型,封装的是PGobject,对于其他类型数据存储方式为字符串类型。 // 返回结果是Table类型。 PgArray pgArray = (PgArray) cs.getObject(4); ResultSet rs = pgArray.getResultSet(); while (rs.next()) { rs.getObject(2);// table类型每行的数据构建成的对象。 } 如果出参的table类型组成为自定义类型,例如create type compfoo_table is table of compfoo,此时接收到的返回对象为PgArray,在通过rs.getObject(2)遍历获取到的组成对象也为PgArray,此时无法获取到组成它的compfoo类型对应的每列数据,需要通过getPGobject()获取到PgObject再操作获取。 调用CallableStatement的close方法关闭调用语句对象cs。 1 cs.close(); A兼容模式开启参数后,调用存储过程必须使用{call proc_name(?,?,?)}形式调用,调用函数必须使用{? = call func_name(?,?)}形式调用(等号左侧的“?”为函数返回值的占位符,用于注册函数返回值)。 参数behavior_compat_options='proc_outparam_override'变更后,业务需要重新建立连接,否则无法正确调用存储过程和函数。 函数和存储过程中包含复合类型时,参数的绑定与注册需要使用schema.typename形式。
  • 创建和调用存储过程 GaussDB 支持通过JDBC调用存储过程,前置条件是数据库建连完成、连接对象为conn。 创建存储过程testproc如下: 1 2 3 4 5 6 7 8 9 10 11 12 // 在数据库中创建如下存储过程,它带有out参数。 CREATE OR REPLACE procedure testproc ( psv_in1 in integer, psv_in2 in integer, psv_inout inout integer ) AS BEGIN psv_inout := psv_in1 + psv_in2 + psv_inout; END; / 调用存储过程testproc如下: 调用Connection的prepareCall方法创建调用语句对象cstmt。 1 CallableStatement cstmt = conn.prepareCall("{? = CALL testproc(?,?,?)}"); 调用CallableStatement的setInt方法设置参数。 1 2 3 cstmt.setInt(2, 50); cstmt.setInt(1, 20); cstmt.setInt(3, 90); 调用CallableStatement的registerOutParameter方法注册输出参数。 1 cstmt.registerOutParameter(4, Types.INTEGER); // 注册out类型的参数,类型为整型。 调用CallableStatement的execute方法执行SQL语句。 1 cstmt.execute(); 调用CallableStatement的getInt方法获取out输出参数。 1 int out = cstmt.getInt(4); 调用CallableStatement的close方法关闭调用语句对象cstmt。 1 cstmt.close(); 一些JDBC驱动程序提供命名参数的方法来设置参数。命名参数的方法允许根据名称而不是顺序来设置参数,若参数有默认值,则可以不用指定参数值就可以使用此参数的默认值。即使存储过程中参数的顺序发生了变更,也不必修改应用程序。目前 GaussDB数据库 的JDBC驱动程序不支持此方法。 GaussDB数据库不支持带有输出参数的函数,也不支持存储过程和函数参数默认值。 使用conn.prepareCall("{? = CALL testproc(?,?,?)}")执行存储过程绑定参数时,可以按照占位符的顺序绑定参数,注册第一个参数为出参。也可以按照存储过程中的参数顺序绑定参数,注册第四个参数为出参,上述用例为此场景,注册第四个参数为出参。 当游标作为存储过程的返回值时,如果使用JDBC调用该存储过程,返回的游标将不可用。 存储过程不能和普通SQL在同一条语句中执行。 存储过程中inout类型参数必须注册出参。
  • 执行普通SQL语句 应用程序通过执行SQL语句来操作数据库,支持对XML类型数据进行SELECT、UPDATE、INSERT、DELETE等操作。 前置条件是已经连接数据库,连接对象为conn。执行普通SQL语句,创建customer_t1表的步骤如下: 调用Connection接口的createStatement方法创建语句对象stmt。 1 Statement stmt = conn.createStatement(); 调用Statement接口的executeUpdate方法执行SQL语句。 1 int rc = stmt.executeUpdate("CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));"); 调用Statement接口的close方法关闭语句对象stmt。 1 stmt.close(); 数据库中收到的一次执行请求(不在事务块中),如果含有多条语句,将会被打包成一个事务,事务块中不支持vacuum操作,如果其中有一个语句失败,那么整个请求都将会被回滚。 使用Statement执行多语句时应以“;”作为各语句间的分隔符,存储过程、函数和匿名块不支持多语句执行。当preferQueryMode=simple,语句执行不进行解析逻辑,此场景下无法使用“;”作为多语句间的分隔符。 “/”可用作创建单个存储过程、函数、匿名块、包体的结束符。当preferQueryMode=simple,语句执行不进行解析逻辑,此场景下无法使用“/”作为结束符。 由于JDBC会对prepareStatement中的SQL语句进行缓存,可能导致内存膨胀,如果JVM内存较小,建议调整preparedStatementCacheSizeMiB或者preparedStatementCacheQueries。
  • 执行预处理更新语句 预编译语句是只编译和优化一次,可以通过设置不同的参数值多次使用。由于已经预先编译好,后续使用会减少执行时间。因此,如果多次执行一条语句,请选择使用预编译语句。 前置条件是执行以上的预处理语句,customer_t1表已经批量插入数据。执行预编译SQL语句对数据进行更新的步骤如下: 调用Connection接口的prepareStatement方法创建预编译语句对象pstmt。 1 PreparedStatement pstmt = conn.prepareStatement("UPDATE customer_t1 SET c_customer_name = ? WHERE c_customer_sk = 1"); 调用PreparedStatement接口的setString方法设置参数。 1 pstmt.setString(1, "new Data"); 调用PreparedStatement接口的executeUpdate方法执行预编译SQL语句。 1 int rowcount = pstmt.executeUpdate(); 调用PreparedStatement接口的close方法关闭预编译语句对象pstmt。 1 pstmt.close(); prepareStatement设置绑定参数后,最终会构建成一个B报文或U报文,在下一步执行SQL语句时发给服务端。但是B报文或U报文有最大长度限制(不能超过1023MB),如果一次绑定数据过大,可能因报文过长导致异常。因此prepareStatement设置绑定参数时需要注意评估和控制绑定数据的大小,避免出现超出报文上限要求的现象。
  • 获取源码包、ODBC包以及依赖库 基于ODBC开发所需的包,依赖库和头文件以及其获取方式如表1所示。 表1 ODBC应用程序开发环境准备 所需资源 获取方式 unixODBC源码包 unixODBC源码包获取参考地址:https://www.unixodbc.org/unixODBC-2.3.7.tar.gz。 MD5文件下载地址:https://www.unixodbc.org/unixODBC-2.3.7.tar.gz.md5。 下载后需使用MD5文件对unixODBC源码包进行完整性校验(查看MD5值,对比MD5值是否与源码包一致)。 Linux系统下的ODBC包以及依赖库 从发布包中获取,包名为GaussDB-Kernel-数据库版本号-操作系统版本号-64bit-Odbc.tar.gz。Linux环境下,开发应用程序要用到unixODBC提供的头文件(sql.h、sqlext.h等)和库libodbc.so。这些头文件和库可从unixODBC-2.3.7的源码包中获得。 Windows系统下的ODBC包以及依赖库 从发布包中获取,包名为GaussDB-Kernel_数据库版本号_Windows_X86_Odbc.tar.gz(32位)和GaussDB-Kernel-数据库版本号-Windows-X64-Odbc.tar.gz(64位)。Windows环境下,开发应用程序用到的相关头文件和库文件由系统自带。 父主题: 开发步骤
  • 关闭连接 ODBC关闭数据库连接,释放资源相关API如表1所示。 表1 相关API说明 功能 API 断开与数据源的连接 SQLDisconnect 释放句柄资源 SQLFreeHandle:释放句柄资源,可替代如下函数: SQLFreeEnv:释放环境句柄 SQLFreeConnect:释放连接句柄 SQLFreeStmt:释放语句句柄 示例如下(完整示例请参考获取和处理数据库中的数据): // 断开数据源连接并释放句柄资源。 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); 父主题: 开发步骤
  • 处理结果集 ODBC处理结果集是从数据库中获取数据并将其提供给应用程序进行处理,作用包括但不限于:检索数据、数据展示、数据处理、数据传输和业务逻辑实现等。 ODBC提供处理结果集的相关API如表1所示。 表1 相关API说明 功能 API 绑定缓冲区到结果集的列中 SQLBindCol 结果集中取行集 SQLFetch 返回结果集中某一列的数据 SQLGetData 获取结果集中列的描述信息 SQLColAttribute 查看最近一次操作错误信息 SQLGetDiagRec 示例如下(完整示例请参考获取和处理数据库中的数据): // 在执行完成SQL语句后,获取结果集某一列的属性。 SQLColAttribute(V_OD_hstmt,1,SQL_DESC_TYPE,typename,100,NULL,NULL); printf("SQLColAtrribute %s\n",typename); // 绑定结果集。 SQLBindCol(V_OD_hstmt,1,SQL_C_SLONG, (SQLPOINTER)&V_OD_buffer,150, (SQLLEN *)&V_OD_err); // 通过SQLFetch取结果集中数据。 V_OD_erg=SQLFetch(V_OD_hstmt); // 通过SQLGetData获取并返回数据。 while(V_OD_erg != SQL_NO_DATA) { SQLGetData(V_OD_hstmt,1,SQL_C_SLONG,(SQLPOINTER)&V_OD_id,0,NULL); printf("SQLGetData ----ID = %d\n",V_OD_id); V_OD_erg=SQLFetch(V_OD_hstmt); }; printf("Done !\n"); 父主题: 开发步骤
  • 执行SQL语句 为了帮助用户实现与数据库的交互,ODBC提供执行SQL语句的相关API如表1所示。 表1 相关API说明 功能 API 设置语句属性 SQLSetStmtAttr 为执行SQL语句做准备 SQLPrepare 执行一条准备好的SQL语句 SQLExecute 绑定SQL语句的参数标志和缓冲区 SQLBindParameter 直接执行SQL语句 SQLExecDirect ODBC为应用程序与数据库的中心层,负责把应用程序发出的SQL指令传到数据库当中,自身并不解析SQL语法。故在应用程序中写入带有保密信息的SQL语句时(如明文密码),保密信息会被暴露在驱动日志中。 数据库中收到的一次执行请求(不在事务块中),如果含有多条语句,将会被打包成一个事务,如果其中有一个语句失败,那么整个请求都将会被回滚。 示例如下(完整示例请参考获取和处理数据库中的数据): // 设置语句属性。 SQLSetStmtAttr(V_OD_hstmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER *)3, 0); // 申请语句句柄。 SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 直接执行SQL语句。 SQLExecDirect(V_OD_hstmt, "drop table IF EXISTS customer_t1", SQL_NTS); SQLExecDirect(V_OD_hstmt, "CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));", SQL_NTS); SQLExecDirect(V_OD_hstmt, "insert into customer_t1 values(25, 'li')", SQL_NTS); // 准备执行。 SQLPrepare(V_OD_hstmt, "insert into customer_t1 values(?)", SQL_NTS); // 绑定参数。 SQLBindParameter(V_OD_hstmt,1, SQL_PA RAM _INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &value, 0, NULL); // 执行准备好的语句。 SQLExecute(V_OD_hstmt); SQLExecDirect(V_OD_hstmt, "select c_customer_sk from customer_t1", SQL_NTS); 父主题: 开发步骤
  • 获取驱动jar包 从发布包中获取驱动jar包,包名为GaussDB-Kernel_数据库版本号_操作系统_64bit_Jdbc.tar.gz(如GaussDB-Kernel_505.2.RC1_Kylin_64bit_Jdbc.tar.gz)。解压后JDBC的驱动jar包: gaussdbjdbc.jar:主类名为“com.huawei.gaussdb.jdbc.Driver”,数据库连接的url前缀为“jdbc:gaussdb”,推荐使用此驱动包。本章的Java代码示例默认使用gaussdbjdbc.jar包。 gscejdbc.jar:主类名为“com.huawei.gaussdb.jdbc.Driver”,数据库连接的url前缀为“jdbc:gaussdb”,此驱动包打包了密态数据库需要加载的加解密相关的依赖库,密态场景推荐使用此驱动包。目前仅支持EulerOS操作系统。 gaussdbjdbc-JRE7.jar:主类名为“com.huawei.gaussdb.jdbc.Driver”,数据库连接的url前缀为“jdbc:gaussdb”,在JDK1.7环境使用gaussdbjdbc-JRE7.jar包。
  • 配置JDK1.8 客户端需配置JDK1.8。JDK支持Windows、Linux等多种平台。下面以Windows为例,配置方法如下。 DOS窗口(windows下的命令提示符)输入以下命令查看JDK版本。 java -version 确认为JDK1.8版本。如果未安装JDK,请从官方网站下载安装包并安装。 根据如下步骤配置系统环境变量。 右键单击“我的电脑”,选择“属性”。 在“系统”页面左侧导航栏单击“高级系统设置”。 在“系统属性”页面,“高级”页签上单击“环境变量”。 在“环境变量”页面上,“系统变量”区域单击“新建”或“编辑”配置系统变量。变量说明如表1所示。 表1 变量说明 变量名 操作 变量值 JAVA_HOME 若存在,则单击“编辑”。 若不存在,则单击“新建”。 JAVA的安装目录。 例如:C:\Program Files\Java\jdk1.8.0_131 Path 单击“编辑”。 若配置了JAVA_HOME,则在变量值的最前面加上: %JAVA_HOME%\bin 若未配置JAVA_HOME,则在变量值的最前面加上 JAVA安装的全路径: C:\Program Files\Java\jdk1.8.0_131\bin CLASSPATH 单击“新建”。 %JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar