2008-04-25
复合主键外连接(2008.4.25笔试)
--测试数据
if exists(select [id] from sysobjects where name='student')
drop table student
go
create table student
(
sname varchar(20) not null,
sclass varchar(20) not null
)
go
alter table student add constraint pk_student primary key(sname,sclass);
go
if exists(select [id] from sysobjects where name='score')
drop table score
go
create table score
(
scoreid int not null primary key identity(1,1),
sname varchar(20) not null,
sclass varchar(20) not null,
score float
)
go
alter table score add constraint fk_score foreign key(sname,sclass) references student(sname,sclass);
go
insert into student values('aaa','1');
insert into student values('ccc','2');
insert into student values('bbb','2');
insert into student values('ddd','2');
insert into student values('ccc','3');
insert into student values('ddd','4');
insert into score(sname,sclass,score) values('aaa',1,66);
insert into score(sname,sclass,score) values('bbb',2,77);
insert into score(sname,sclass,score) values('ccc',2,88);
insert into score(sname,sclass,score) values('ddd',4,99);
/*
--外键插入null值
insert into score(score) values(66);
insert into score(score) values(77);
insert into score(score) values(77);
*/
select * from student;
select * from score;
--复合主键内连接
select * from student t inner join score s on t.sname = s.sname and t.sclass = s.sclass;
--复合主键左外连接
select t.sname,t.sclass from student t left outer join score s on t.sname = s.sname and t.sclass = s.sclass where s.scoreid is null;
测试过程中发现= null和is null的区别,特引用下面一篇文章加以说明:
SQL Server Null的比较运算(转)
今天我在写sql的时候发现用
UPDATE dbo.tblInvTransaction
SET Area_Type = 'Gross',
WHERE (Area_Type = null)
结果为零。
然后查到下面这个文章
改成
UPDATE dbo.tblInvTransaction
SET Area_Type = 'Gross'
WHERE (Area_Type is NULL )
就ok了
前几天写一个数据库查询程序,碰到的一个问题,是关于SQL Server的Null值的比较运算的。一般情况下我们查询空值或者非空值的时候,用的是is null/is not null,而很少用=/<>。但是在我的这个程序中,没有用is这样的关键字,而是用=/<>这样的比较元算符号,这就碰到了一些问题。
问题起源于一个Web查询页面,因为问题比较复杂的,所以简化一下来说明。
在页面上用户可以自由选择数据表的某些字段,填写该字段的查询条件,先是选择比较运算符号(=,<>等),然后填写值。提交之后,就需要创建一个SQL语句,查询条件的各部分由不同的程序模块创建。这里涉及两个程序模块,一个模块根据提交创建比较运算符号,一个模块负责创建比较值模块。在创建值模块中有这样一个规则,“如果提交的值是空的,把该值设为Null”。
但是我发现,如果比价值为Null的时候,同样一个SQL查询语句放在存储过程里边查询和通过应用程序直接查询的结果是不一样的。
查了查SQL Server文档,发现Null值的比较运算,存在两种规则:
在SQL2000中Null值的比较运算有两种规则。一种是ANSI SQL(SQL-92)规定的Null值的比较取值结果都为False,既Null=Null取值也是False。另一种不准循ANSI SQL标准,即Null=Null为True。
以一张表T的查询为例。
表T存在下面的数据:
RowId Data
--------------
1 'test'
2 Null
3 'test1'
按照ANSI SQL标准,下面的两个查询都不返回任何行:
Query1: select * from T where Data=null
Query2: select * from T where Data<>null
而按照非ANSI SQL标准,查询1将返回第二行,查询2返回1、3行。
ANSI SQL标准中取得Null值的行需要用下面的查询:
select * from T where Data is null
反之则用is not null。由此可见非ANSI SQL标准中Data=Null等同于Data Is Null,Data<>Null等同于Data Is Not Null。
而控制采用那一种规则,需要使用命令SET ANSI_NULLS [ON/OFF]。ON值采用ANSI SQL标准,OFF值采用非标准模式。另外SET ANSI_DEFAULTS [ON/OFF]命令也可以实现标准的切换,只是这个命令控制的是一组符合SQL-92标准的设置,其中就包括Null值的标准。
默认情况下,数据库管理程序(DB-Library)是SET ANSI_NULLS为OFF的。但是我们的大多数应用程序,都是通过ODBC或者OLEDB来访问数据库的,作为一种开放兼容的数据库访问程序,或许是兼容性的考虑,SET ANSI_NULLS值设置为ON。这样一来带来的一些问题是需要注意的。像存储过程或者自定义函数这样的应用程序都是基于DB-Library的,默认情况下,SET ANSI_NULLS为OFF,并且在这样的程序中,不能使用SET ANSI_NULLS在一个环境中修改规则,只能修改数据库配置参数。
考虑下面这种情况。
你的应用程序使用ADODB来访问数据库,采用OleDb或者ODBC数据提供程序。对于前面的查询1:
select * from T where Data=null
你可以直接发送命令取得结果集,也可以把它放到存储过程当中。但是他们的查询结果是不一样的。如果直接使用查询命令,什么结果也没有,而如果访问存储过程,你获得第2行的数据。
我写了一个.Net程序来验证这一点。同时也为了验证.Net SqlClient的SET ANSI_NULLS的设置,由于SqlClient不是通过OleDb或者ODBC这些数据提供程序来访问SQL Server,而是直接对SQL Server进行访问,本来我以为它会采用SQL Server默认的设置,但是结果恰恰相反,它的默认设置和OleDb、ODBC一样。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Odbc;
public class AnsiNullsTest{
public static void Main(String[] args){
IDbConnection conn;
String connType = "SqlClient";
if(args.Length>0)connType = args[0];
if(connType.ToUpper()=="OLEDB"){
Console.WriteLine("Connection Type:OLEDB");
conn = new OleDbConnection("Provider=SQLOLEDB.1;User ID=sa;PWD=test;Initial Catalog=TEST;Data Source=TEST");
}else if(connType.ToUpper()=="ODBC"){
Console.WriteLine("Connection Type:ODBC");
conn = new OdbcConnection("Driver={SQL Server};UID=sa;PWD=test;Database=TEST;Server=TEST");
}else{
Console.WriteLine("Connection Type:SQLClient");
conn = new SqlConnection("Server=TEST;Database=TEST;User ID=sa;PWD=test");
}
Test(conn);
}
public static void Test(IDbConnection conn){
String query1 = "select 'Test' where null=null";
String query2 = "exec p_Test"; //存储过程中是一样的SQL语句
IDbCommand cmd;
IDataReader reader;
Console.WriteLine("print 'Test' set ansi_nulls off");
try{
cmd = conn.CreateCommand();
conn.Open();
cmd.CommandText = query1;
reader = cmd.ExecuteReader();
Console.WriteLine("command:" + query1);
while(reader.Read()){
Console.WriteLine("result:" + reader[0].ToString());
}
reader.Close();
cmd.CommandText = query2;
reader = cmd.ExecuteReader();
Console.WriteLine("command:" + query2);
while(reader.Read()){
Console.WriteLine("result:" + reader[0].ToString());
}
reader.Close();
}
catch(Exception ex){
Console.WriteLine(ex.Message);
}
finally{
conn.Close();
}
}
}
它有一个参数,根据参数采用不同的参数值采用不同的数据库访问程序。命令对象作了两次查询,一次是SQL查询命令,一次是调用存储过程。语句都是一样,但是结果不一样。
发表评论
- 浏览: 3562 次
- 性别:

- 来自: 杭州

- 详细资料
搜索本博客
我的相册
CommandPattern2
共 11 张
共 11 张
最近加入圈子
链接
- 在项目中整合FCKeditor
- HTML编辑器FCKeditor使用详解
- 将SQL Server 2005中的数据同步到Oracle中
- SQL 连接 oracle 方法
- 异地SQL Server与Oracle数据同步解决方案
- SqlServer下数据库链接的使用方法
- 随机数生成算法
- JavaScript中的正则表达式解析
- 英文自我介绍-简历
- java面试笔试题大汇总
- Lucene:基于Java的全文检索引擎简介
- 浅谈B/S系统安全
- Oracle中的Hash Join祥解
- Hash join算法原理
- oralce学习笔记之异常处理篇
- 转发和重定向的区别
- 外企面试顺利通关全攻略
- 我的google面试经历
- 分析in和exists的区别与执行效率的问题
- 北航BBS上遇小强,贴出来,激励自己
- hibernate实体对象
- Hibernate中实体对象的生命周期
- Hibernate 实体对象的状态及转化
- 易保面试题
- 易保面试,英文翻译题
- Java编译器对于String常量表达式的优化
- Java中static 和final的区别
- SQL Group by 学习
- Oracle SQL99 外连接的写法区别
- Struts开发指南之工作流程
- 从800到了15000 -- 一个非科班三流大学程序员的路程
- SQL 语句中特殊字符的处理及预防sql 注射
- 记一次对20NT安全小组的渗透测试
- E-R图
- 数据库系统设计
- 数据结构学习笔记(转载)
- Spring中WebApplicationContext的研究
- BeanFactory及ApplicationContext的基本原理
- 与高手共事
- 阿里软件招JAVA工程师面试题
- Spring的事件处理机制陷阱
- org.hibernate.FlushMode
- 优化Oracle数据库性能
- SQL语句性能调整原则
- Oracle调优综述
- Oracle DBA优化数据库性能心得体会
- 说说大型高并发高负载网站的系统架构
- web架构设计经验分享
- DDOS
- jBPM开发入门指南
- 轻松实现Apache,Tomcat集群和负载均衡
- 结合Apache和Tomcat实现集群和负载均衡
- Tomcat性能优化笔记
- Tomcat性能调整
- Oracle语句优化规则汇总
- ASP.NET是否可以和JSP公用一个Session或Cookie?
- Leo——感谢生活!
- Oracle 5大ACE谈数据库技术学习
- 如何学习Oracle-eygle的方法经验谈
- 可伸缩性最佳实践:来自eBay的经验
- 关于Oracle学习以及DBA工作机会
- Architecture相关架构的学习
- 架构师书单 2nd Edition
- IT学习力
最新评论
-
Struts-html标签好用吗?
我觉得就是一种规定和标准,大家都用,一看就明白了。 至于和普通的html相比,我 ...
-- by gitahwang -
Struts-html标签好用吗?
BirdGu 写道javaboy2006 写道抛出异常的爱 写道不喜欢就用< ...
-- by javaboy2006 -
Struts-html标签好用吗?
javaboy2006 写道抛出异常的爱 写道不喜欢就用<%%> 反正有3 ...
-- by 抛出异常的爱 -
Struts-html标签好用吗?
javaboy2006 写道抛出异常的爱 写道不喜欢就用<%%> 反正有3 ...
-- by BirdGu -
Struts-html标签好用吗?
抛出异常的爱 写道不喜欢就用<%%>反正有30%的需求都必须用《%%》才能 ...
-- by javaboy2006






评论排行榜