㈠ 第三章 sql语言元素(一)
InterSystems SQL命令(也称为SQL语句)以关键字开头,后跟一个或多个参数。其中一些参数可能是子句或函数,由它们自己的关键字标识。
InterSystems SQL关键字包括命令名称,函数名称,谓词条件名称,数据类型名称,字段约束,优化选项和特殊变量。它们还包括 AND , OR 和 NOT 逻辑运算符, NULL 列值指示符以及ODBC函数构造,例如 {d dateval} 和 {fn CONCAT(str1,str2)} 。
聚合函数是SQL固有函数,它计算列的所有值并返回单个聚合值。
这种写法只能在mac routine里,类文件里编译报错。
如果将用户提供的(外部)函数的使用配置为系统范围的选项,则该SQL语句只能调用用户提供的(外部)函数。默认为“否”。默认情况下,尝试调用用户提供的函数会发出 SQLCODE -372 错误。可以使用 %SYSTEM.SQL类的SetAllowExtrinsicFunctions() 方法在系统范围内配置SQL对外部函数的使用。若要确定当前设置,请调用 $SYSTEM.SQL.CurrentSettings() ,该显示显示“允许在SQL语句中使用外部函数”选项。
不能使用用户提供的函数来调用 %routine (名称以%字符开头的例程)。
尝试这样做会发出 SQLCODE -373 错误。
InterSystems SQL文字具有以下语法:
文字是一系列代表实际(文字)值的字符。它可以是数字或字符串。
空字符串是文字字符串;它由两个单引号字符( '' )表示。 NULL 不是文字值;它表示没有任何值。
注意:在嵌入式SQL中,不允许在字符串文字中使用以 ## 开头的一些字符序列,如“使用嵌入式SQL”一章的“文字值”中所述。此限制不适用于其他SQL调用,例如动态SQL。
使用单引号( ' )字符作为字符串定界符。 SQL兼容性支持双引号字符( “ )的使用,但由于与定界标识符标准冲突,因此强烈建议不要使用。将一对双引号字符 "" 解析为无效的定界标识符。并生成 SQLCODE -1 错误。
要在字符串中指定单引号字符作为字面字符,请指定一对这样的字符作为字面转义序列。
例如, 'a 'normal' string' 。
双竖条( || )是首选的SQL连接操作符。
它可以用于连接两个数字、两个字符串或一个数字和一个字符串。
下划线( _ )作为SQL连接操作符提供,以保证ObjectScript的兼容性。
此连接操作符只能用于连接两个字符串。
如果两个操作数都是字符串,并且两个字符串都具有相同的排序规则类型,则所得的级联字符串具有该排序规则类型。在所有其他情况下,连接的结果是排序类型 EXACT 。
使用 NULL 关键字表示没有指定值。
在SQL中, NULL 始终是表示数据值因任何原因未指定或不存在的首选方式。
SQL零长度字符串(空字符串)由两个单引号字符指定。
空字符串( " )与空字符串是不同的。
空字符串是一个已定义的值,一个不包含字符的字符串,一个长度为0的字符串。
一个零长度的字符串在内部由非显示字符 $CHAR(0) 表示。
注意:不建议使用SQL零长度字符串作为字段输入值或字段默认值。
使用 NULL 表示数据值的缺失。
在SQL编码中应避免使用SQL零长度字符串。
但是,由于许多SQL操作都会删除末尾的空格,所以只包含空格字符(空格和制表符)的数据值可能会导致SQL的零长度字符串。
注意,不同的SQL length函数返回不同的值: length 、 CHAR_LENGTH 和 DATALENGTH 返回SQL长度。
$LENGTH 返回ObjectScript表示长度。
长度不计算尾随空格;
所有其他长度函数都计算末尾的空格。
NOT NULL数据约束要求字段必须接收一个数据值;
不允许指定NULL而不是值。
这个约束不阻止使用空字符串值。
SELECT 语句的 WHERE 或 HAVING 子句中的 IS NULL 谓词选择空值;
它不选择空字符串值。
IFNULL 函数计算一个字段值,如果字段值为 NULL ,则返回第二个参数中指定的值。
它不会将空字符串值视为非空值。
COALESCE 函数从提供的数据中选择第一个非空值。
它将空字符串值视为非空值。
当 CONCAT 函数或 concenate 操作符( || )连接一个字符串和一个 NULL 时,结果是 NULL 。
如下面的例子所示:
AVG、COUNT、MAX、MIN 和 SUM 聚合函数在执行操作时忽略 NULL 值。
( COUNT * 统计所有行,因为不可能有一个所有字段都为空值的记录。)
SELECT 语句的 DISTINCT 关键字在其操作中包含 NULL ;
如果指定的字段有空值, DISTINCT 返回一个空行.
AVG 、 COUNT 和 MIN 、聚合函数受空字符串值的影响。
MIN 函数将空字符串视为最小值,即使存在值为0的行。
MAX 和 SUM 聚合函数不受空字符串值的影响。
对大多数SQL函数提供 NULL 作为操作数将返回 NULL 。
任何以NULL作为操作数的SQL算术操作都返回 NULL 值。
因此,7 +零=零。
这包括二元运算加法( + )、减法( - )、乘法( * )、除法( / )、整数除法( )和取模( # ),以及一元符号运算符加号( + )和减号( - )。
算术操作中指定的空字符串将被视为0(零)值。
除法( / ),整数除法( ),或对空字符串( 6/ " )取模( # )会导致 <DIVIDE> 错误。
在SQL中, NULL 的长度是没有定义的(它返回 < NULL > )。
然而,空字符串的长度被定义为长度为0。
如下面的例子所示:
如本例所示,SQL LENGTH 函数返回SQL长度。
可以使用 ASCII 函数将SQL的零长度字符串转换为 NULL ,示例如下:
但是,对标准 SQL 的某些系统间IRIS扩展对 NULL 和空字符串的长度的处理是不同的。
$LENGTH函数返回这些值的InterSystems IRIS内部表示: NULL 表示为长度为0的已定义值,SQL空字符串表示为长度为0的字符串。
该功能与ObjectScript兼容。
这些值的内部表示方式的另一个重要位置是 %STRING 、 %SQLSTRING 和 %SQLUPPER 函数,它们将空格附加到值中。
因为 NULL 实际上没有值,所以在它后面添加一个空格会创建一个长度为1的字符串。
但是一个空字符串确实有一个字符值,所以在它后面加上一个空格会创建一个长度为2的字符串。
如下面的例子所示:
注意,这个例子使用的是 CHAR_LENGTH ,而不是 LENGTH 。
因为 LENGTH 函数删除了末尾的空格,所以 LENGTH(%STRING(NULL)) 返回长度为0的字符串;
LENGTH(%STRING(")) 返回长度为2的字符串, 因为 %STRING 追加的是前导空格,而不是尾随空格。
当SQL NULL 输出到ObjectScript时,它由ObjectScript空字符串( "" )表示,长度为0的字符串。
当SQL零长度字符串数据输出到ObjectScript时,它由包含 $CHAR(0) 的字符串表示,该字符串长度为1。
在ObjectScript中,没有值通常用空字符串( "" )表示。
当这个值被传递到嵌入式SQL中时,它会被视为空值,如下面的例子所示:
如果指定了一个未定义的输入主机变量,嵌入式SQL将其值视为 NULL 。
当将NULL或空字符串值从嵌入式SQL传递到ObjectScript时, NULL 被转换为长度为0的字符串,空字符串被转换为长度为1的字符串。
如下面的例子所示:
在下面的例子中,SQL的空字符串加上一个空格被传递为长度为2的字符串:
㈡ 第142章 SQL函数 TO_CHAR(三)
以下嵌入式 SQL 示例显示了基本的数字到字符串的转换:
返回具有适当数量的前导空格的指定数字。无符号正数前面总是有一个空白字漏衡卖符。如果指定数字的位数少于格式参数,则提供额外的前导空格。
以下嵌入式 SQL 示例显示了分隔符的使用:
第一个 TO_CHAR 返回字符串 '1,000.00' ;。第二个 TO_CHAR 也可能返回此值,但显示的分隔符取决于区域设置。
以下嵌入式 SQL 示例显示了正号和负号的使用:
请注意,前导空格拦陆仅出现在没有符号格式的正数之前。无论符号的位置如何,负数或任何带符号的数字之前都不会出现前导空格。
以下嵌入式 SQL 示例显示了使用“FM”格式覆盖无符号正返逗数的默认前导空白:
以下嵌入式 SQL 示例显示了前导美元符号的使用:
美元符号前面总是有一个符号或一个空白字符。
以下嵌入式 SQL 示例显示了当 format 参数包含的整数位数少于输入数值时会发生什么:
每个 TO_CHAR 分别返回一串井号: “##” 、 “###” 和 “######” 。
以下嵌入式 SQL 示例显示了当 format 参数包含的十进制(小数)位数少于输入数值表达式时会发生什么:
返回的数字分别四舍五入为 “1234567.5” 和 “1234568” 。
㈢ 北京理工大学远程教育学院.计算机专业.数据库技术与应用在线作业求答案
理工网络教育的卷子,没有标准答案。需要他人帮做各种作业,就加一下本人吧。
㈣ 静态SQL和动态SQL的区别和测试实例
所谓SQL的动态和静态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的。
静态SQL:在高级语言中,如果嵌入了SQL语句,而这个SQL语句的主体结构已经明确,例如在c的一段代码中有一个待执行的SQL“select * from t1 where c1>5”,在编译阶段,就可以将这段SQL交给数据库管理系统去分析,数据库软件可以对这段SQL进行语法解析,生成数据库方面的可执行代码,这样的SQL称为静态SQL,即在编译阶段就可以确定数据库要做什么事情。
动态SQL:如果嵌入的SQL没有明确给出,如在c中定义了一个字符数组类型的变量name:char name[32];,然后采用prepared Statement对象的execute方法去执行这个sql,该sql的值可能等于从文本框中读取的一个SQL或者从键盘输入的SQL,但具体是什么,在编译时无法确定,只有等到程序运行起来,在执行的过程中才能确定,这种SQL叫做动态SQL。例如每一种数据库软件都有能够执行SQL语句的界面,那个界面接收的SQL就是动态SQL,因为数据库厂商在做这个界面时,并不知道用户会输入哪些SQL,只有在该界面执行后,接收了用户的实际输入,才知道SQL是什么。
注意:在SQL中如果某些参数没有确定,如”select * from t1 where c1>? and c2#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE SQLDA;
/*此函数属于静态SQL编程*/
int DBSelect_static(){
EXEC SQL BEGIN DECLARE SECTION;
char _typename[32];
short _length;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT typename,length
INTO :_typename,:_length
FROM syscat.columns
WHERE tabname='SYSCOLUMNS' and colname='DEFAULT';
printf("【typename:%s】【length:%d】\n",_typename,_length);
}
/*此函数属于静态SQL编程:指定函数参数作为SQL语句的变量*/
int DBSelect_static_param(char *tbl_str,char *col_str){
EXEC SQL BEGIN DECLARE SECTION;
char _typename1[32];
short _length1;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT typename,length
INTO :_typename1,:_length1
FROM syscat.columns
WHERE tabname='tbl_str' and colname='col_str';
printf("【typename:%s】【length:%d】\n",_typename1,_length1);
}
/*此函数属于动态SQL编程:SQL语句的结构是不确定的,需要根据用户的输入补全SQL语句*/
int DBUpdate_dynamic(){
EXEC SQL BEGIN DECLARE SECTION;
char _address1[32];
char _tablename[32];
char _tmp[32];
char buf[256];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT count(address1) INTO :_tmp FROM cisaddressinfo WHERE customid='100000100000000000178';
if(0==_tmp) {printf("Not Found!\n");return -1;}
memset(buf,0x00,sizeof(buf));
sprintf(buf,"update ");
printf("Pls input : tablename ->");
scanf("%s",&_tablename);
strcat(buf,_tablename);
strcat(buf," set address1=? where customid='100000100000000000178'");
EXEC SQL PREPARE project FROM :buf;
if(sqlca.sqlcode) perror("PREPARE");
printf("Pls input : address1 ->");
scanf("%s",&_address1);
EXEC SQL EXECUTE project USING :_address1;
if(sqlca.sqlcode) perror("EXECUTE");
EXEC SQL COMMIT WORK;
if(sqlca.sqlcode) perror("COMMIT");
}
/*此函数属于动态SQL编程:使用sqlda数据结构组装复杂多变的动态SQL*/
int DBSelect_dynamic(){
EXEC SQL BEGIN DECLARE SECTION;
char hostVarStmt[256];
EXEC SQL END DECLARE SECTION;
// 声明两个 SQLDA 指针,minsqlda 将是一个最小的 SQLDA 结构,用于 PREPARE 语句,
// 此时结果集的字段数量未知,所以只需一个最小的 SQLDA,即包含 HEADER 和一个 SQLVAR
struct sqlda * minsqlda = (struct sqlda*)malloc(SQLDASIZE(1));
struct sqlda * fulsqlda = NULL;
strcpy(hostVarStmt, "select WUID from workprocess where muid = '185001'");
// PREPARE 将填写 minsqlda 的 header,sqldabc 为 SQLDA 总长度,sqln 为 SQLVAR 数量,即字段数量
EXEC SQL PREPARE STMT INTO :*minsqlda FROM :hostVarStmt;
// 根据从 minsqlda 中获取的长度,分配完整的 SQLDA 结构 fulsqlda,其中将包括合适数量的 SQLVAR 结构
//结构sqlda的成员变量sqld返回select查询语句的字段的数目,可以根据此变量分配内存
fulsqlda = (struct sqlda *)malloc(SQLDASIZE(minsqlda->sqld));
// 使用 DESCRIBE 语句,获取结果集中每个字段的描述信息,包括各字段的类型 (sqltype) 和长度 (sqllen)
EXEC SQL DESCRIBE STMT INTO :*fulsqlda;
int i;
for(i=0;i<minsqlda->sqld;i++)
{
// 根据每个字段的长度,分配内存,将地址存储在对应 SQLVAR 的 sqldata 中
// fulsqlda->sqlvar[i].sqldata=malloc(fulsqlda->sqlvar[i].sqllen);
fulsqlda->sqlvar[i].sqldata=malloc(32);
fulsqlda->sqlvar[i].sqlind=malloc(sizeof(short));
}
// 声明游标
EXEC SQL DECLARE c1 CURSOR FOR STMT;
EXEC SQL OPEN c1;
EXEC SQL WHENEVER not found goto no_more_data;
// 读取记录,记录中每个字段的内容将写入 fulsqlda 中对应 SQLVAR 结构的 sqldata 指向的内存
// EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
// 循环读取所有记录
for (;;)
{
EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
for(i=0;i<minsqlda->sqld;i++){
printf("%d %s\n",fulsqlda->sqlvar[i].sqltype,fulsqlda->sqlvar[i].sqldata);
usleep(10000);
}
}
return 0;
no_more_data:
printf("\nEND of Data\n");
free(minsqlda);
free(fulsqlda);
EXEC SQL CLOSE c1;
return 0;
}
int main(){
/*连接数据库*/
EXEC SQL CONNECT TO ezeelink USER ezeelink USING EA704075ezeelink;
DBSelect_static();
DBSelect_static_param("SYSCOLUMNS","DEFAULT");
DBUpdate_dynamic();
DBSelect_dynamic();
no_more_data:
;
return 0;
}
案例输出结果如下:
【typename:VARCHAR】【length:254】
【typename:VARCHAR】【length:254】
Pls input : tablename ->cisaddressinfo
Pls input : address1 ->ShangHai
452 cis505
452 cis506
452 pub806
452 ips007
452 ips032
452 dps302
END of Data
注意:
如果使用动态SQL编程编写select查询语句并保存结果,需要使用sqlda数据结构的,同时使用SQL的特性和功能,如:PREPARE ,EXECUTE ,DESCRIBE , DECLARE CURSE C1 FOR … , OPEN CURSE , CLOSE CURSE ….等等
建议:
动态SQL适用于表名及查询字段名未知的情况。在已知查询字段名及表名的情况下,使用动态SQL(字符串拼接方式)会增加硬解析的开销,在这种情况下,建议使用静态SQL,这样可以提高执行效率。在过程过程用拼凑的动态sql效率并不高,有时候还不如程序直接传递sql.静态SQL是前置编译绑定,动态SQL是后期执行时才编译绑定
㈤ C语言中使用嵌入式sql
嵌入式SQL程序的VC+SQL server 2000实现的环境配置
嵌入SQL的C应用程序具体到VC++6.0, SQL Server2000 下调试可分为五步:1、环境初始化;2、预编译;3、编译;4、连接;5、运行。下面就其中重要的的操作方法给以详细说明。
1、环境初始化
(1) SQL Server2000为其嵌入式SQL提供了一此特殊的接口;默认的安装方式没有安装这此接口;因此,需要把devtools.rar解压到SQLServer的系统日录下(即文件夹devtools中的所有文件);如果操作系统安装在C盘,则SQL Server的系统目录是C:\Program Files\Microsoft SQL Server。(或 在安装Microsoft SQL Server 2000时选择安装Development Tools,为使用嵌入式SQL语言准备必要的头文件和库文件。)
( 2)初始化Visual C++ 6.0编译器环境。在命令行方式下运行文件\Microsoft Visual Studio\VC98\Bin\vcvars32.bat。
(3)初始化SQL Server的预编译环境。在命令行方式下运行文件:\Devtools\samples\esqlc\setenv.bat。
( 4) VC++6.0环境配置。具体配置分为如下三步[:
①Tools->options->directories->Include Files:添加 C:\Program Files\Microsoft SQL Server\devtools\include。将SQL server自带的用于数据库开发的头文件包含到工程环境中。
②Tools->options->directories->Lib Files:添加C:\Program Files\Microsoft SQL Server\devtools\x861ib。将开发用到的包包含到工程中。
③project->Settings->Link->Object/Library Moles,添加库文件:SQLakw32.lib, Caw32.lib。这两个文件之间用空格分开。
2、预编译
C语言编译程序不能识别应用程序中的SQL语句,需要经过预处理程序将其转换成C语句。SQL Server的预处理程序是nsqlprep.exe。 nsqlprep.exe在SQL Server安装日录的MSSQL\Binn下。若SQL Server数据库采用的是默任安装方式,则需要把binn.rar的内容拷贝到指定目录下。
Microsoft SQL Server 2000提供的预编译程序nsqlprep.exe,用于对嵌入式SQL程序进行预编译处理,生成C语言源程序.实际上就是将嵌入式SQL程序中的嵌入式SQL语句替换为对运行时库文件Sqlakw32. dll的函数调用,接着运行时库文件调用动态连接库Ntwdblib. dll通过网络来存取Microsoft SQL Server 2000数据库服务器.
预编译程序nsqlprep的常用语法为:
nsqlprep ESQL_File /SQLACCESS /DB server_name.database_name /PASS login.password
其中ESQL_File是要预编译的嵌入式SQL程序;/SQLACCESS通知nsqlprep自动地为嵌入式SQL程序中的静态SQL语句创建相应的存储过程;/DB server_name.database_name指明要连接的服务器以及数据库名称;/PASS login.password给出登录名及相应的口令.
下面的程序demo.sqc实现了从数据库服务器hushaobo的数据库pubs中的authors表中读取au_lname为white的人对应的 au_fname 值,并保存到变量first_name 中显示出来。(连接数据库的用户为sa,对应密码为1982)
#include<stdio.h>
void main()
{
EXEC SQL BEGIN DECLARE SECTION;
char first_name[40];
char last_name[]="White";
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO hushaobo.pubs
USER sa.1982;
EXEC SQL SELECT au_fname INTO :first_name from authors WHERE au_lname = :last_name;
EXEC SQL DISCONNECT ALL;
printf("first name: %s \n",first_name);
}
在命令行下运行:nsqlprep demo.sqc /SQLACCESS /DB hushaobo.pubs /PASS sa.1982
则生成demo.c,将该文件添加到VC工程中编译即可。
3、编译,连接与运行
在VC++6.0中创建一个 "WIN32 Console Application"的Proiect,然后将预编译生成的c文件加入Proiect,编译连接即可生成访问SQL Server的可执行程序。 Visual C++ 6.0进行编译连接时需要用到动态链接库SQLakw32.d11与SQLaiw32.d11;尽管这两个文件已经随同binn.rar被拷贝到SQLServer安装目录的MSSQL\Binn文件夹下,但仍然需要把它们的路径加到系统路径变量中,以使得程序运行时能找到它们,具体添加方法如下:
方法1:把这两个文件拷贝到操作系统目录下的system32子目录中。
方法2:我的电脑->属性->高级->环境变量->path->编辑,在变量值中加入路径值;新路径与已有路径间用;间隔。
注意调适程序时,文件名中不要包含cursor,否则可能会出错。
㈥ 数据库嵌入式sql编程,求解
题目没有说明表之间的外键关系,那我就默认同名的列名是外键,不清楚你用的编程语言,所以我使用:input作为输入变量
1
select Teacher.Tname,Teacher.Tage,Teacher.Tsex,Work.Salary from Teacher,Work,Department
where Teacher.Tno=Work.Tno and Department.Dno=Work.Dno
and Department.Tno=Teacher.Tno and Work.Salary>:input
2
update Work set Salary=:input from Teacher,Department
where Teacher.Tno=Work.Tno and Department.Dno=Work.Dno
and Department.Tno=Teacher.Tno and Work.Salary<:input
㈦ 交互式SQL与嵌入式SQL有什么不同
1、语言不同
交互式SQL是指在终端交互方式下使用的SQL语言称为交互式SQL;嵌入式SQL是一种将SQL语句直接写入C语言,COBOL,FORTRAN, Ada等编程语言的源代码中的方法。
2、使用不同
交互式SQL是在终端交互方式下使用;嵌入式SQL是嵌入在高级语言的程序中使用。
(7)数据库嵌入式sql章节测验扩展阅读:
提供对于嵌入式SQL的支持,需要数据库厂商除了提供DBMS之外,还必须提供一些工具。为了实现对于嵌入式SQL的支持,技术上必须解决以下4个问题:
1、宿主语言的编译器不可能识别和接受SQL文,需要解决如何将SQL的宿主语言源代码编译成可执行码;
2、宿主语言的应用程序如何与DBMS之间传递数据和消息;
3、如何把对数据的查询结果逐次赋值给宿主语言程序中的变量以供其处理;
4、数据库的数据类型与宿主语言的数据类型有时不完全对应或等价,如何解决必要的数据类型转换问题。
嵌入式SQL源码的处理流程 为了解决上述这些问题,数据库厂商需要提供一个嵌入式SQL的预编译器,把包含有嵌入式SQL文的宿主语言源码转换成纯宿主语言的代码。
这样一来,源码即可使用宿主语言对应的编译器进行编译。通常情况下,经过嵌入式SQL的预编译之后,原有的嵌入式SQL会被转换成一系列函数调用。因此,数据库厂商还需要提供一系列函数库,以确保链接器能够把代码中的函数调用与对应的实现链接起来。