返回首页

gbase数据、南大通用产品文档:GBase8s使用某些 SQL 语句发生的排他锁

更新日期:2024年09月11日


GBase 8s SQL 指南:教程
南大通用数据技术股份有限公司
- 256 -
当您执行 INSERT、UPDATE 或 DELETE 语句时,数据库服务器使用排他锁。排他锁意
味着任何其他用户都不可更新或删除该项,直到数据库服务器移除该锁为止。此外,任何
其他用户都不可查看该行,除非他们正在使用 Dirty Read 隔离级别。

数据库服务器移除排他锁的时刻,依赖于该数据库是否支持事务日志记录。
要获取关于这些排他锁的更多信息,请参阅使用 INSERT、UPDATE 和 DELETE 语句加
上的锁定。

dtcvfmtasc() 函数使用格式化掩码来将字符串转换为 datetime 值。
语法
mint dtcvfmtasc(inbuf, fmtstring, dtvalue)
char *inbuf;
char *fmtstring;
dtime_t *dtvalue;
inbuf
指向包含要转换的字符串的缓冲区的指针。
fmtstring
指向要针对 inbuf 字符串使用其格式化掩码的缓冲区的指针。此时间格式化掩码包含
DBTIME 环境变量支持的相同的格式化伪指令。
dtvalue
指向初始化了的 datetime 变量的指针。

用法
您必须以您想要此变量拥有的限定符来初始化 dtvalue 中的 datetime 变量。
datetime
变量不需要指定该格式化掩码说明的同一限定符。
当 datetime 限定符与说明了的格式化掩
码限定符不同时,dtcvfmtasc() 扩展 datetime 值(如同它以调用了 dtextend() 函数)。


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 679 -
inbuf 中的字符串中的所有限定符字段都必须是相邻的,换句话说,如果限定符为
hour to second,
则您必须为该字符串中某处的 hour、
minute 和 second 都指定值,
否则,
dtcvfmtasc() 函数返回错误。
inbuf 字符串可有开头的和结尾的空格。然而,从第一个有效位至最后一个,inbuf 仅
可包含适于格式化掩码说明的限定符字段的数字和定界符。

如果格式化掩码 fmtstring 为空字符串,
则 dtcvfmtasc() 函数返回错误。
如果 fmtstring
是空指针,则当 dtcvfmtasc() 函数读取 inbuf 中的字符串时,它必须确定格式。当您使用
缺省的语言环境时,该函数使用下列优先顺序:
DBTIME 环境变量指定的格式(如果设置 DBTIME 的话)。
GL_DATETIME 环境变量指定的格式(如果设置 GL_DATETIME 的话)。
符合标准 ANSI SQL 格式的缺省的日期格式:
%iY-%m-%d %H:%M:%S

ANSI SQL 格式为输出指定 year to second 的限定符。您可以四位(2007)或以两位
(07)表示年份。当您在格式化掩码中使用两位年份(%y)时,dtcvfmtasc() 函数使用
DBCENTURY 环境变量的值来确定要使用哪个世纪。如果您未设置 DBCENTURY,则
dtcvfmtasc() 为两位年份假定当前的世纪。

当您使用非缺省的语言环境(US English 之外的一种),且未设置 DBTIME 或
GL_DATETIME 环境变量时,dtcvfmtasc() 使用该语言环境定义的缺省的 DATETIME 格
式。

当字符串和格式化掩码是可接受的时,dtcvfmtasc() 函数设置 dtvalue 中的 datetime
变量,并返回零。否则,它返回错误代码,且 datetime 变量包含不可预计的值。

返回代码
0
转换成功。
<0
转换失败。

示例


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 680 -
demo 目录在文件 dtcvfmtasc.ec 中包含此样例程序。该代码将变量 birthday 初始化
为虚构的生日。
/* *dtcvfmtasc.ec*
The following program illustrates the conversion of several ascii strings into datetime
values.
*/

#include

EXEC SQL include datetime;

main()
{
char out_str[17], out_str2[17], out_str3[17];
mint x;

EXEC SQL BEGIN DECLARE SECTION;
datetime month to minute birthday;
datetime year to minute birthday2;
datetime year to minute birthday3;
EXEC SQL END DECLARE SECTION;

printf("DTCVFMTASC Sample ESQL Program running.\n\n");

/* Initialize birthday to "09-06 13:30" */
printf("Birthday #1 = September 6 at 01:30 pm\n");
x = dtcvfmtasc("September 6 at 01:30 pm", "%B %d at %I:%M %p",
&birthday);

/*Convert the internal format to ascii in ANSI format, for displaying. */
x = dttoasc(&birthday, out_str);
printf("Datetime (month to minute) value = %s\n\n", out_str);
/* Initialize birthday2 to "07-14-88 09:15" */

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 681 -
printf("Birthday #2 = July 14, 1988. Time: 9:15 am\n");
x = dtcvfmtasc("July 14, 1988. Time: 9:15am",
"%B %d, %Y. Time: %I:38p", &birthday2);

/*Convert the internal format to ascii in ANSI format, for displaying. */
x = dttoasc(&birthday2, out_str2);
printf("Datetime (year to minute) value = %s\n\n", out_str2);
/* Initialize birthday3 to "07-14-XX 09:15" where XX is current year.
* Note that birthday3 is year to minute but this initialization only
* provides month to minute. dtcvfmtasc provides current information for the
missing year.
*/
printf("Birthday #3 = July 14. Time: 9:15 am\n");
x = dtcvfmtasc("July 14. Time: 9:15am", "%B %d.
Time: %I:%M %p",&birthday3);

/* Convert the internal format to ascii in ANSI format, for displaying. */
x = dttoasc(&birthday3, out_str3);
printf("Datetime (year to minute) value with current year = %s\n", out_str3);

printf("\nDTCVFMTASC Sample Program over.\n\n");

}
输出
DTCVFMTASC Sample ESQL Program running.

Birthday #1 = September 6 at 01:30 pm
Datetime (month to minute) value = 09-06 13:30

Birthday #2 = July 14, 1988 Time: 9:15 am
Datetime (year to minute) value = 2007-07-14 09:15

Birthday #3 = July 14. Time: 9:15 am

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 682 -
Datetime (year to minute) value with current year = 2007-07-14 09:15

DTCVFMTASC Sample Program over.

JDBC 资料未指定 Struct 对象可作为 PreparedStatement.setObject() 方法的参数。
然而,
GBase
8s JDBC Driver 可处理实现 java.sql.Struct接口
的 PreparedStatement.setObject() 或 ResultSet.getObject() 方法处理的任何对象。
必须使用 Struct 接口来访问未命名的行。

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 129
-
无需创建自己的类来实现 java.sql.Struct 接口。然而,在您可插入或更新 ROW 数据之前,
必须执行访存来检索 ROW 数据和类型信息。GBase 8s JDBC Driver 自动地调
用 getSQLTypeName() 方法,其返回命名的行的类型名称,或未命名的行的行定义。
如果创建自己的类来实现 Struct 接口,则您创建的类必须实现所有 java.sql.Struct 方法,包
括 getSQLTypeName() 方法。您可选择getSQLTypeName() 方法返回什么。
虽然必须返回未命名的行的行定义,但是,您可返回命名的行的行名称或行定义。每一个
都有优点:

行定义。驱动程序无需为了类型信息查询数据库服务器。此外,返回的行定义不必
与命名的行定义完全匹配,
因为数据库服务器提供强制转型,
如果需要的话。
例如,
如果想要使用字符串来插入至行中的 opaque 类型,则这是有用的。

行名称。如果用户定义的例程采用命名的行作为参数,则签名必须匹配,因此,您
必须在命名的行中传递。
要获取关于用户定义的例程的更多信息,
请参数下列出版物:
J/Foundation 开发者指南(特
定于 Java™ 的信息);GBase 8s 用户定义的例程和数据类型开发者指南 和 GBase 8s SQL
指南:参考(都是关于用户定义的例程的通用信息);GBase 8s SQL 指南:语法(创建和
调用用户定义的例程的语法)。
重要: 如果为命名的行使用 Struct 接口,并为命名的行提供类型映射信息,则当调
用 ResultSet.getObject() 方法时,
会产生 ClassCastException 信息,
因为 Java 不可在 SQLData 对
象与 Struct 对象之间强制转型。
Struct 示例
本部分中所有示例的完整版本位于安装了驱动程序处的 demo/complex-types 目录中。要获
取更多信息,请参阅 示例代码文件。
此示例访存未命名的 ROW 列。这里是样例数据库模式:
CREATE TABLE teachers
(
person row(
id int,
name row(first char(20), last char(20)),
age int
),
dept char(20)
);
INSERT INTO teachers VALUES ("row(100, row('Bill', 'Smith'), 27)",
"physics");
这是该示例的剩余部分:
PreparedStatement pstmt;

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 130
-
ResultSet rs;
pstmt = conn.prepareStatement("select person from teachers");
System.out.println("prepare ...ok");
rs = pstmt.executeQuery();
System.out.println("executetQuery()...ok");

rs.next();
Struct person = (Struct) rs.getObject(1);
System.out.println("getObject()...ok");
System.out.println("\nData fetched:");

Integer id;
Struct name;
Integer age;
Object[] elements;

/* Get the row description */
String personRowType = person.getSQLTypeName();
System.out.println("person row description: " + personRowType);
System.out.println("");

/* Convert each element into a Java object */
elements = person.getAttributes();

/*
* Run through the array of objects in 'person' getting out each structure
* field. Use the class Integer instead of int, because int is not an object.
*/
id = (Integer) elements[0];
name = (Struct) elements[1];
age = (Integer) elements[2];
System.out.println("person.id: " + id);
System.out.println("person.age: " + age);
System.out.println("");

/* Convert 'name' as well. */
/* get the row definition for 'name' */
String nameRowType = name.getSQLTypeName();

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 131
-
System.out.println("name row description: " + nameRowType);

/* Convert each element into a Java object */
elements = name.getAttributes();

/*
* run through the array of objects in 'name' getting out each structure
* field.
*/
String first = (String) elements[0];
String last = (String) elements[1];
System.out.println("name.first: " + first);
System.out.println("name.last: " + last);
pstmt.close();
如果列 1 是 ROW 类型,
且没有扩展的数据类型名称
(如果它是命名的行的话)

则 Struct
person = (Struct) rs.getObject(1) 语句实例化一个 Struct 对象。
elements = person.getAttributes(); 语句执行下列活动:

以正确的元素数分配一个 java.lang.Object 对象的数组

将该行中每一元素转换为一 Java™ 对象
如果该元素为 opaque 类型,则必须在 Connection 对象中提供类型映射,或在
对 getAttributes() 方法的调用中传递一个java.util.Map 对象。
String personrowType = person.getSQLTypeName(); 语句返回行类型信息。
如果此类型为命名
的行,则该语句返回名称。由于类型不是命名的行,因此,该语句返回行定义:row(int id,
row(first char(20), last char(20)) name, int age).
然后,该示例进入未命名的行 name 的后续步骤,如同对未命名的行 person 一样。
下列示例使用用户创建的类 GenericStruct,其实现 java.sql.Struct 接口。作为替代,您可使
用从 ResultSet.getObject() 方法返回的 Struct 对象,而不是 GenericStruct 类。
import java.sql.*;
import java.util.*;
public class GenericStruct implements java.sql.Struct
{
private Object [] attributes = null;
private String typeName = null;

/*
* Constructor

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 132
-
*/
GenericStruct() { }

GenericStruct(String name, Object [] obj)
{
typeName = name;
attributes = obj;
}
public String getSQLTypeName()
{
return typeName;
}
public Object [] getAttributes()
{
return attributes;
}
public Object [] getAttributes(Map map) throws SQLException
{
// this class shouldn't be used if there are elements
// that need customized type mapping.
return attributes;
}
public void setAttributes(Object [] objArray)
{
attributes = objArray;
}
public void setSQLTypeName(String name)
{
typeName = name;
}
}
下列 Java 程序插入一 ROW 列:
PreparedStatement pstmt;
ResultSet rs;
GenericStruct gs;
String rowType;

pstmt = conn.prepareStatement("insert into teachers values (?, 'Math')");

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 133
-
System.out.println("prepare insert...ok\n");

System.out.println("Populate name struct...");
Object[] name = new Object[2];

// populate inner row first
name[0] = new String("Jane");
name[1] = new String("Smith");

rowType = "row(first char(20), last char(20))";
gs = new GenericStruct(rowType, name);
System.out.println("Instantiate GenericStructObject...okay\n");

System.out.println("Populate person struct...");
// populate outer row next
Object[] person = new Object[3];
person[0] = new Integer(99);
person[1] = gs;
person[2] = new Integer(56);

rowType = "row(id int, " +
"name row(first char(20), last char(20)), " +
"age int)";
gs = new GenericStruct(rowType, person);
System.out.println("Instantiate GenericStructObject...okay\n");

pstmt.setObject(1, gs);
System.out.println("setObject()...okay");
pstmt.executeUpdate();
System.out.println("executeUpdate()...okay");
pstmt.close();
在此示例中的 pstmt.setObject(1, gs) 语句处,GBase 8s JDBC Driver 确定要从客户机传至数
据库服务器的信息作为 ROW 列,因为GenericStruct 对象是 java.sql.Struct 接口的一个实例。

序列化数组中的每一元素,核实每一元素与由 getSQLTypeName() 方法定义的类型相匹配。