Net.Data 提供了关系数据库语言环境,帮助您访问关系数据资源。 您提供的 用来存取关系数据的 SQL 语句,将作为动态 SQL 执行。有关动态 SQL 的详情,可参见 DB2 文档。
以下章节描述语言环境以及如何使用这些语言环境:
开放数据库连接 (ODBC) 语言环境通过一个 ODBC 接口执行 SQL 语句。 ODBC 是 基于 X/Open SQL CAE 规格说明的,它允许单一的应用访问多个数据库管理系统。
要使用 ODBC 语言环境:
要使用 ODBC 语言环境,首先应获取并安装 ODBC 驱动程序和驱动程序管理器。您的 ODBC 驱动程序文档描述了如何安装和配置 ODBC 环境。
验证 Net.Data 初始化文件中是否有以下配置语句,并且是在一行上。
ENVIRONMENT (DTW_ODBC) d:/net.data/lib/dtwodbc.dll ( IN DATABASE, LOGIN, PASSWORD, TRANSACTION_SCOPE, START_ROW_NUM, DTW_SET_TOTAL_ROWS)
限制:
您使用的数据库可能有不同的限制;请参考您的数据库文档以确定对该数据库的限制是否有所不同。
Oracle 语言环境提供了对 Oracle 数据的本机访问。 可以在使用 CGI、FastCGI、NSAPI、 ISAPI 或 GWAPI 时,从 Net.Data 访问 Oracle 数据库。本语言环境支持 Oracle 7.2、7.3 和 8.0。
要使用 Oracle 语言环境,验证初始化文件中是否有以下配置语句,并且是在一行上。
ENVIRONMENT (DTW_ORA) /net.data/lib/dtwora.so ( IN DATABASE, LOGIN, PASSWORD, TRANSACTION_SCOPE, START_ROW_NUM, DTW_SET_TOTAL_ROWS)
参见设置 Oracle 语言环境以了解如何进一步设置 Oracle 语言环境。
限制:
LOGON=admin@ora73
SQL 语言环境提供了对 DB2 数据库的访问。在访问 DB2 时,使用此语言环境以获得最佳的性能。
要使用 SQL 语言环境,验证初始化文件中是否有以下配置语句,并且是在一行上。
ENVIRONMENT (DTW_SQL) d:/net.data/lib/dtwsql.dll (IN DATABASE, LOGIN, PASSWORD, TRANSACTION_SCOPE, START_ROW_NUM, DTW_SET_TOTAL_ROWS)
嵌套 SQL 语句
您可在另一 SQL 函数中调用这些 SQL 函数。如果传送的是表,则确保您在每个函数中使用的表名唯一; 否则,可能会产生意外的结果。
示例:从 ROW 块或另一个 SQL 函数调用 SQL 函数
%define mytable1 = %TABLE %define mytable2 = %TABLE %FUNCTION(DTW_SQL) sql2 (IN p1, OUT t2) { select * from NETDATA.STAFFINF where projno='$(p1)' %REPORT { %ROW { $(N1) is $(V1) %} %} %} %FUNCTION(DTW_SQL) sql1 (OUT t1) { select * from NETDATA.STAFFINF %REPORT { %ROW { @sql2(V1, mytable2) %} %} %} %HTML(netcall1) { @sql1(mytable1) %}
限制:
内联语句块中的 SQL 语句最长可达 64 KB。 DB2 Universal Database 具有以下限制:
您使用的数据库可能有不同的限制;请参考您的数据库文档以确定对该 DBMS 的限制是否有所不同。
嵌套 SQL 只可在 SQL 或 ODBC 语言环境中使用,而不能与 Live Connection 一起使用。
嵌套 SQL 语句时,结果集的最大数目是 32。例如, 可嵌套三层,每层返回 10 个结果集。或嵌套 32 层,每层返回一个结果集。
当使用 insert、delete 或 update 语句修改数据库的内容时,只有当数据库接收到来自 Net.Data 的落实语句,这些修改才会变为永久性的修改。如果发生错误,Net.Data 将向数据库发送一个回滚语句,撤消上一次落实之后所作的全部修改。
Net.Data 发送落实和回滚的方式取决于 TRANSACTION_SCOPE 的设置以及宏中是否显式地指定了落实语句。TRANSACTION_SCOPE 的值可以是 MULTIPLE 和 SINGLE。
指定 Net.Data 在每个成功完成的 SQL 语句后都发出一个落实语句。如果 SQL 语句返回错误,则发出一个回滚语句。单次事务作用域确保了数据库修改的立即性;但是使用此作用域之后, 今后就不可能使用回滚语句来撤消所做的修改。
要激活这种落实方法,可将 TRANSACTION_SCOPE 设置为 SINGLE。例如:
@DTW_ASSIGN(TRANSACTION_SCOPE,"SINGLE")
指定 Net.Data 将在发出落实以及可能的回滚语句之前执行所有的 SQL 语句。Net.Data 在请求的最后发送落实,如果每个 SQL 语句都已成功发出,落实将使数据库中所有的修改都变为永久性的修改。如果其中有任何一个语句返回错误,Net.Data 都将发出一个回滚语句,该语句将把数据库设置回原来的状态。如果没有 TRANSACTION_SCOPE, 则缺省值是 MULTIPLE。
通过使用 COMMIT SQL 语句,就可以在宏中每个 SQL 语句之后发出一个落实语句。保持 TRANSACTION_SCOPE 设置 为 MULTIPLE 的状态并在您觉得可以作为一个事务来对待的每组语句的最后发出落实语句,这样, 您这个应用程序开发者就可以对应用程序中的落实和回滚行为进行完全的控制。例如,在每次对宏进行更新之后发出落实语句将有助于确保数据的完整性。
要发出 SQL 落实语句,可以定义一个能在 HTML 块中任意位置调用的函数:
%FUNCTION(DTW_SQL) user_commit() { commit %} ... %HTML { ... @user_commit() ... %}
限制:
在连接数据库之后,便不能更改 TRANSACTION_SCOPE 的设置。因此, 宏中的所有 SQL 事务都属于同一作用域。
如果使用 Net.Data 作为 Net.Commerce 的一部分,则需注意,Net.Commerce 有它自己的事务处理,并禁用了 Net.Data 的事务处理。
您可将大对象文件 (LOB) 存储在 DB2 数据库中, 并通过使用 Net.Data SQL 或 ODBC 语言环境将它们合并到动态 Web 页面中。
如果语言环境执行了 SQL SELECT 语句或返回 LOB 的存储过程,则它不会将该对象指定给 V(n) 表处理变量或 Net.Data 表字段。而是将 LOB 存储在 Net.Data 创建的,并仅在 V(n) 表处理变量或 Net.Data 表字段中返回文件名的一个文件。 在 Net.Data 宏中,可使用该名称来引用 LOB 文件;例如, 可创建一个 HTML 锚元素,并带有超文本引用或包含该文件的 URL 的映象元素。 Net.Data 将包含 LOB 的文件放置在由 HTML_PATH 路径语句指定的目录中, 该语句位于 Net.Data 初始化文件 (db2www.ini) 中。 对 LOB 文件的写存取权受与检索该 LOB 的 Net.Data 请求相关联的用户 ID 的限制。
LOB 的文件名是以动态方式构造的,具有以下格式:
name[.extension]
其中:
扩展名 | 对象类型 |
---|---|
.bmp | 位图图象 |
.gif | 图形图象格式 |
.jpg | 联合摄影专家组 (JPEG) 图象 |
.tif | 标记图象文件格式 |
.ps | 附录 |
.mid | 乐器数字接口 (midi) 音频 |
.aif | AIFF 音频 |
.avi | 音频可视交替音频 |
.au | 基本音频 |
.ra | 实际音频 |
.wav | 窗口音频可视 |
便携式文档格式 | |
.rmi | midi 序列 |
如果 BLOB 的对象类型不被识别,则不会对文件名添加任何扩展名。
如果 Net.Data 返回包含 LOB 的文件名, 则它会使用以下语句来对文件名加上字符串 /tmplobs/ 以作为前缀:
/tmplobs/name.[extension]
此前缀允许您将 LOB 目录放在不同于 Web 服务器的文档根目录的目录中。
要确保能够对 LOB 文件的引用进行正确地解析, 将以下 Pass 指令添加至 Web 服务器的配置文件:
Pass /tmplobs/* <html_path>/tmplobs/*
<html_path> 是对 Net.Data 初始化文件中的 HTML_PATH 路径语句指定的值。
规划提示: 返回 LOB 的每个查询会在由 HTML_PATH 路径配置变量指定的目录中创建文件。 考虑使用 LOB 时的系统限制(这是由于 LOB 迅速消耗资源而造成的)。 您可能想要定期清除该目录, 或执行 dtwclean 精灵程序。参见管理临时 LOB以了解详情。 建议使用 DataLinks,它会消除 SQL 语言环境对在目录中存储文件的需求, 从而使性能更好,且使用的系统资源也更少一些。
示例:以下应用程序使用 MPEG 音频 (.mpa) 文件。因为 SQL 语言环境不识别此文件类型, 所以 EXEC 变量用来将 .mpa 扩展名追加至文件名。 此应用程序的用户必须单击文件才能调用 MPEG 音频文件查看器。
%DEFINE{ docroot="/usr/lpp/internet/server_root/html" myFile=%EXEC "rename $(docroot)$(filename) $(docroot)$(filename).mpa" %} %{ where rename is the command on your operating system to rename files %} %FUNCTION(DTW_SQL) queryData() { SELECT Name, IDPhoto, Voice FROM RepProfile %REPORT{ <p>Here is the information you selected:</p> %ROW{ @DTW_ASSIGN(filename, @DTW_rSUBSTR(V3, @DTW_rLASTPOS("/", V3))) $(myFile) $(V1) <img src="$(V2)"> <a href="$(V3).mpa">Voice sample</a><p> %} %} %} %HTML(REPORT){ @queryData() %}
如果 RepProfile 表包含有关 Kinson Yamamoto 和 Merilee Lau 的信息,则执行 REPORT 块将会把以下 HTML 添加至生成的 Web 页面:
<p>Here is the information you selected:</p> Kinson Yamamoto <img src="/tmplobs/p2345n1.gif"> <a href="/tmplobs/p2345n2.mpa">Voice sample</a><p> Merilee Lau <img src="/tmplobs/p2345n3.gif"> <a href="/tmplobs/p2345n4.mpa">Voice sample</a><p>
上一示例中的 REPORT 块使用了隐式表变量 V1、V2 和 V3。
对 LOB 的存取权:
LOB 的缺省 tmplobs 目录在由 HTML_PATH(在交付的 Net.Data 初始化文件中)指定的目录下。它可由任何用户 ID 进行存取。 如果 HTML_PATH 值发生了更改,确保 Web 服务器用来运行的用户 ID 对由 HTML_PATH 指定的目录具有写存取权(参见HTML_PATH以了解详情)。
管理临时 LOB:
Net.Data 将临时 LOB 存储在子目录 tmplobs 中, 该子目录在由 HTML_PATH 路径配置变量指定的目录下。 这些文件可能很大,应定期清除以维护适当的性能。
Net.Data 提供了一个精灵程序 dtwclean, 它会协助您定期管理 tmplobs 目录。 dtwclean 使用端口 7127。
要运行 dtwclean 精灵程序: 从命令行窗口输入以下命令:
dtwclean [-t xx] [-d|-l]
其中:
存储过程是一个存储在 DB2 中的编译程序,它可执行 SQL 语句。在 Net.Data 中,存储过程是使用 CALL 语句从 Net.Data 函数调用的。存储过程参数是从 Net.Data 函数参数列表中传送的。 可通过使编译的 SQL 语句与数据库服务器保持一致以使用存储过程来改进性能和完整性。 Net.Data 支持通过 SQL 和 ODBC 语言环境来将存储过程与 DB2 配合使用。
本节描述了下列主题:
存储过程的语法使用 FUNCTION 语句、CALL 语句, 并可选择使用 REPORT 块。
%FUNCTION (DTW_SQL) function_name ([IN datatype arg1, INOUT datatype arg2, OUT tablename, ...]) { CALL stored_procedure [(resultsetname, ...)] [%REPORT [(resultsetname)] { %}] ... [%REPORT [(resultsetname)] { %}] [%MESSAGE %}] %}
其中:
BIGINT | DOUBLEPRECISION | SMALLINT |
CHAR | FLOAT | TIME |
CLOB1 | INTEGER | TIMESTAMP |
DATE | GRAPHIC | VARCHAR |
DECIMAL | LONGVARCHAR | VARGRAPHIC |
DOUBLE | LONGVARGRAPHIC |
|
1 CLOB 仅可用作 OUT 和 INOUT 参数,且 Net.Data 按字节说明大小。 例如,如果将变量指定为 OUT CLOB(20000), 则大小为 20K 的 CLOB 将要用作输出参数。 |
%FUNCTION (DTW_SQL) function_name()
%FUNCTION (DTW_SQL) function_name (IN datatype arg1, INOUT datatype arg2, OUT tablename...)
CALL stored_procedure
%REPORT (resultsetname) { ... %}
示例:
%FUNCTION (DTW_SQL) mystoredproc (IN CHAR(30) arg1) { CALL myproc %REPORT (mytable){ ... %ROW { ... %} ... %} %}
CALL stored_procedure (resultsetname1, resultsetname2, ...)
%REPORT(resultsetname1) { ... %}
示例:
%FUNCTION (DTW_SQL) mystoredproc (IN CHAR(30) arg1, OUT table1) { CALL myproc (table1, table2) %REPORT (table2) { ... %ROW { ... %} ... %} %}
可将参数传送至存储过程,并让存储过程更新参数值,以使新值传送回 Net.Data 宏。 函数参数列表上的参数数目和类型必须与对存储过程定义的数目和类型相匹配。 例如,如果对存储过程定义的参数列表上的参数是 INOUT, 则函数参数列表上的对应参数必须是 INOUT。 如果对存储过程定义的列表上的参数类型为 CHAR(30), 则函数参数列表上的对应参数必须也是 CHAR(30)。
示例 1: 将参数值传送至存储过程
%FUNCTION (DTW_SQL) mystoredproc (IN CHAR(30) valuein) { CALL myproc ...
示例 2: 从存储过程返回值
%FUNCTION (DTW_SQL) mystoredproc (OUT VARCHAR(9) retvalue) { CALL myproc ...
您可使用 SQL 或 ODBC 语言环境从存储过程返回一个或多个结果集。 结果集可存储在 Net.Data 表中,以在宏内进行进一步的处理, 或是使用 REPORT 块进行处理。如果存储过程生成了多个结果集, 则您必须将名称与由存储过程生成的每个结果集相关联。 这是通过在 CALL 语句上指定参数来完成的。 然后,可将对结果集指定的名称与 REPORT 块或 Net.Data 表相关联, 这允许您确定 Net.Data 将如何来处理每一个结果集。 您可:
参见多个 REPORT 块的准则和限制以了解使用多个报告块时的基准和限制。
要返回单个结果集并使用缺省报告:
使用以下语法:
%FUNCTION (DTW_SQL) function_name () { CALL stored_procedure %}
例如:
%FUNCTION (DTW_SQL) mystoredproc() { CALL myproc %}
要返回单个结果集并指定 REPORT 块:
使用以下语法:
%FUNCTION (DTW_SQL) function_name () { CALL stored_procedure [(resultsetname)] %REPORT [(resultsetname)] { ... %} %}
例如:
%FUNCTION (DTW_SQL) mystoredproc () { CALL myproc %REPORT { ... %ROW { ... %} ... %} %}
或者,可使用以下语法:
%FUNCTION (DTW_SQL) function_name () { CALL stored_procedure (resultsetname) %REPORT (resultsetname) { ... %} %}
例如:
%FUNCTION (DTW_SQL) mystoredproc () { CALL myproc (mytable1) %REPORT (mytable1) { ... %ROW { ... %} ... %} %}
要将单个结果集存储在 Net.Data 表中以进行进一步的处理:
使用以下语法:
%FUNCTION (DTW_SQL) function_name (OUT tablename) { CALL stored_procedure (resultsetname) %}
例如:
%DEFINE DTW_DEFAULT_REPORT = "NO" %FUNCTION (DTW_SQL) mystoredproc (OUT mytable1) { CALL myproc (mytable1) %}
注意,DTW_DEFAULT_REPORT 被设置为 NO 以便不对结果集生成缺省报告。
要返回多个结果集并使用缺省报告格式来显示它们:
使用以下语法:
%FUNCTION (DTW_SQL) function_name () { CALL stored_procedure [(resultsetname1, resultsetname2, ...)] %}
其中未指定任何报告块。
例如:
%DEFINE DTW_DEFAULT_REPORT = "YES" %FUNCTION (DTW_SQL) mystoredproc () { CALL myproc %}
要返回多个结果集, 并将结果集存储在 Net.Data 表中以进行进一步的处理:
使用以下语法:
%FUNCTION (DTW_SQL) function_name (OUT tablename1, tablename2, ...) { CALL stored_procedure (resultsetname1, resultsetname2, ...) %}
例如:
%DEFINE DTW_DEFAULT_REPORT = "NO" %FUNCTION (DTW_SQL) mystoredproc (OUT mytable1, mytable2) { CALL myproc (mytable1, mytable2) %}
注意,DTW_DEFAULT_REPORT 被设置为 NO, 以便不对结果集生成缺省报告。
要返回多个结果集, 并对显示处理指定 REPORT 块:
每个结果集都与它的一个或或多个 REPORT 块相关联。 使用以下语法:
%FUNCTION (DTW_SQL) function_name (, ...) { CALL stored_procedure (resultsetname1, resultsetname2, ...) %REPORT (tablename1) ... %ROW { ... %} ... %} %REPORT (tablename2) ... %ROW { ... %} ... %} ... %}
例如:
%FUNCTION (DTW_SQL) mystoredproc () { CALL myproc (mytable1, mytable2) %REPORT(mytable1) { ... %ROW { ... %} ... %} %REPORT(mytable2) { ... %ROW { ... %} ... %} %}
要返回多个结果集并对每个结果集指定不同的显示或处理选项:
可使用唯一参数名来对每个结果集指定不同的处理选项。 例如:
%FUNCTION (DTW_SQL) mystoredproc (OUT mytable2) { CALL myproc (mytable1, mytable2, mytable3) %REPORT(mytable1) ... %ROW { ... %} ... %} %}结果集 mytable1 是由对应的 REPORT 块进行处理的,并按宏编写者所指定的那样显示。 结果集 mytable2 存储在 Net.Data 表 mytable2 中,且现存可用于进一步的处理, 如传送至另一函数。结果集 mytable3 是使用 Net.Data 的缺省报告格式显示的, 原因是未对其指定任何 REPORT 块。
DataLink 是一种基本构造块,用于扩展可以存储在数据库文件中的数据类型。通过使用 DataLink, 存储在列中的实际数据便只是一个指向文件的指针了。这个文件可以是任何类型的文件;图象文件、语音记录或文本文件。DataLink 存储 URL 以便分辨文件的位置。
DATALINK 数据类型需要使用 DataLink 文件管理器。有关 DataLink 文件管理器的更多信息, 参见针对您的操作系统的 DataLink 文档。使用 DATALINK 数据类型之前,必须确保 Web 服务器对 DB2 文件管理器服务器所管理的文件系统具有访问权。
当 SQL 查询使用 DataLink 返回结果集时,将用具有 READ PERMISSION DB DataLink 选项的 FILE LINK CONTROL 创建 DataLink 列,DataLink 列中的文件路径包含一个访问令牌。DB2 使用访问令牌来授予对文件的访问权。没有这个访问令牌,所有对该文件的访问都将因权限违例而失败。当然, 访问令牌中可能包含要返回给浏览器的 URL 中不能使用的字符,例如分号字符 (;)。例如:
/datalink/pics/UN1B;0YPVKGG346KEBE;baibien.jpg
URL 无效,因为它包含分号 (;) 字符。要使该 URL 有效,必须使用 Net.Data 内部函数 DTW_URLESCSEQ 对该分号进行编码。当然,有些字符串处理必须在使用此函数之前执行,因为这个函数也将对斜线 (/) 进行编码。
可以编写一个 Net.Data MACRO_FUNCTION 来自动进行字符串处理并使用 DTW_URLESCSEQ 函数。在每个从 DATALINK 数据类型列中检索数据的宏中使用此技术。
例 1:一个使 DB2 UDB 返回的 URL 自动编码的 MACRO_FUNCTION
%{ TO DO: Apply DTW_URLESCSEQ to a DATALINK URL to make it a valid URL. IN: DATALINK URL from DB2 File Manager column. RETURN: The URL with token portion is URL encoded %} %MACRO_FUNCTION encodeDataLink(in DLURL) { @DTW_rCONCAT( @DTW_rDELSTR( DLURL, @DTW_rADD(@DTW_rLASTPOS("/", DLURL), "1" ) ), @DTW_rURLESCSEQ( @DTW_rSUBSTR(DLURL, @DTW_rADD( @DTW_rLASTPOS("/", DLURL), "1" ) ) ) ) %}
在使用此 MACRO_FUNCTION 之后,URL 即被正确编码,DATALINK 列中指定的文件就可以在 任何 Web 浏览器上引用。
例 2:一个 Net.Data 宏,指定返回 DATALINK URL 的 SQL 查询
%FUNCTION(DTW_SQL)myQuery(){ select name, DLURLCOMPLETE(picture) from myTable where name like '%river%' %REPORT{ %ROW{ <p> $(V1) <br /> Before Encoding: $(V2) <br /> After Encoding: @encodeDataLInk($(V2)) <br /> Make HREF: <a href="@encodeDataLink($(V2))"> click here </a> <br /> <p> %} %} %}
请注意,这里使用了 DataLink “文件管理器”函数。函数 dlurlcomplete 返回一个完整的 URL。
以下示例显示如何从宏调用关系数据库语言环境:
以下示例为 ODBC 语言环境定义和调用多个函数。
%DEFINE{ DATABASE="qesq1" SHOWSQL="YES" table="int_null" LOGIN="netdata1" PASSWORD="ibmdb2"%} %function(dtw_odbc) sq1() { create table int_null (int1 int, int2 int) %} %function(dtw_odbc) sql2() { insert into $(table) (int1) values (111) %} %function(dtw_odbc) sql3() { insert into $(table) (int2) values (222) %} %function(dtw_odbc) sql4() { select * from $(table) %} %function(dtw_odbc) sql5() { drop table $(table) %} %HTML(REPORT){ @sql1() @sql2() @sql3() @sql4() %}
%DEFINE{ LOGIN="ulogin" PASSWORD="upassword" DATABASE="" table= "utable" %} %FUNCTION(DTW_ORA) myQuery(){ select ename,job,empno,hiredate,sal,deptno from $(table) order by ename %} %MESSAGE{ 100 : "<b>WARNING</b>: No employee were found that met your search criteria.<p>" : continue %} %HTML(REPORT){ @myQuery() %}
以下示例显示了具有 DTW_SQL 函数定义的宏(该函数定义调用一个 SQL 存储过程)。 它有三个不同 数据类型的参数。DTW_SQL 语言环境根据参数的数据类型将每个参数传递给存储过程。当存储过程完成处理之后, 将返回输出参数,Net.Data 也将相应地更新变量。
%{*********************************************************** DEFINE BLOCK ************************************************************%} %DEFINE{ MACRO_NAME = "TEST ALL TYPES" DTW_HTML_TABLE = "YES" Procedure = "TESTTYPE" parm1 = "1" %{SMALLINT %} parm2 = "11" %{INT %} parm3 = "1.1" %{DECIMAL (2,1) %} %} %FUNCTION(DTW_SQL) myProc (INOUT SMALLINT parm1, INOUT INT parm2, INOUT DECIMAL(2,1) parm3){ CALL $(Procedure) %} %HTML(REPORT){ <head> <title>Net.Data : SQL Stored Procedure: Example '$(MACRO_NAME)'. </title> </head> <body bgcolor="#bbffff" text="#000000" link="#000000"> <p><p> Calling the function to create the stored procedure. <p><p> @CRTPROC() < hr> <h2> Values of the INOUT parameters prior to calling the stored procedure:<p> </h2> <b>parm1 (SMALLINT)</b><br /> $(parm1)<p> <b>parm2 (INT)</b><br /> $(parm2)<p> <b>parm3 (DECIMAL)</b><br /> $(parm3)<p> <p> < hr> <h2> Calling the function that executes the stored procedure. </h2> <p><p> @myProc(parm1,parm2,parm3) < hr> <h2> Values of the INOUT parameters after calling the stored procedure:<p> </h2> <b>parm1 (SMALLINT)</b><br /> $(parm1)<p> <b>parm2 (INT)</b><br /> $(parm2)<p> <b>parm3 (DECIMAL)</b><br /> $(parm3)<p> </body> %}