项目需要这样的转换,发现有些视图转换后查询死机,经过一番研究, 终于有点收获:

原来的死机sql:(简化过)

SELECT  产品ID,
          (SELECT SUM(数量)
         FROM dbo.nowlib nowlib
         WHERE nowlib.产品ID = Product.产品ID) AS 现存数量, 预警上限, 预警下限,
          (SELECT 预警上限 - SUM(数量)
         FROM dbo.nowlib nowlib
         WHERE nowlib.产品ID = Product.产品ID) AS 缺货数量, 通用名, 输入码, 品名, 产地,
      规格, 单位, 包装, 剂型, 零售价, 批发价, 近期进价, 批准文号
FROM dbo.PRODUCT Product
GROUP BY 产品ID, 通用名, 输入码, 品名, 产地, 规格, 单位, 包装, 剂型, 零售价, 批发价,
      近期进价, 批准文号, 预警上限, 预警下限
ORDER BY 品名, 产地

上面的sql在sqlserver中完全正常,但是access中修改过一点语法区别后仍死机,经过试验发现第一个子查询是正常的,第二个会出错。研究后发现如果子查询中出现了:预警上限,就会出错,这是主表PRODUCT 中的字段,所以推论是如果子表出现主表的字段,就会出错(where后面用于连接的id不算)。

修改后的sql语句可以正常了,像下面这样(简化过):

SELECT 产品ID, 预警上限, 预警下限, 通用名, 输入码, 品名, 产地, 规格, 单位, 包装, 剂型, 零售价, 批发价, 近期进价, 批准文号,

(SELECT SUM(n3.数量) as tmp
FROM nowlib as n3         
WHERE n3.产品ID = pro.产品ID) AS 总数量3, 预警上限-总数量3 AS 缺货数量

FROM PRODUCT AS Pro
GROUP BY 产品ID, 通用名, 输入码, 品名, 产地, 规格, 单位, 包装, 剂型, 零售价, 批发价, 近期进价, 批准文号, 预警上限, 预警下限
ORDER BY 品名, 产地;

-------------------------------------------------------------------------------------------------------------------------------------------

原来access还有这样一个‘特色’,写出来给那些仍然正在郁闷中的人解脱一下。对了,网上找到一些资料,是关于SQL Server转换为 Access时候需要注意的问题,一并列出:

-------------------------------------------------------------------------------------------------------------------------------------------

最近正在升级一个程序,使其支持多数据库。
原来的程序数据库为SQL Server,所以使用SQL Server 的“导入和导出数据”功能将一个 SQL Server 数据库转换成了Access数据库,但其中发现了一些问题,但也找到了解决方案,一并记录于此:

1、转换程序会将SQL Server的视图转换成表,而不是Access的查询;
2、在为字段设置默认值为空字符的时候,SQL Server用‘’(空单引号),而Access用“”(空双引号);
3、Access中没有GetDate()函数,应该使用Now()函数代替;
4、Access没有SQL Server用来获取客户端机器名的host_name()函数;
5、Access中没有Case When Then语句,但可以用IIF()函数模拟实现功能;
6、发现:Access使用的是Visual Basic的语言结构和函数;
7、转换程序会正确转换SQL Server字段的 IS NULL 属性;
8、Access也支持多字段的索引,只是设置方法有点特别(参见帮助);
9、SQL Server中bit型的1、0值,在Access中为True和False;
10、在Access中使用多个LEFT JOIN这样的语句时,必须用括号做相关的界定;
11、Access的SQL没有注释语句,SQL Server的/**/无法通用;
12、一条Insert语句在Access查询中正常运行,但在程序中出现“Insert Into 语句的语法错误”,后来发现原来是语句中的一个列名是Access的关键字(用〔〕界定可解决问题),但奇怪的是将该语句放置到Access的查询中执行却不会出错。

需要对转换后的Access数据库进行以下项目的检查,以确保与SQL Server一致:

1、主键。转换后的Access数据库都没有主键,需自己设置;
2、自增字段。转换程序会将SQL Server的自增字段转换为数字型,需手动修改为Access的“自动编号”类型;
3、默认值。转换程序不会转换SQL Server中设置的默认值,需手动设置;
4、bigint型字段。转换程序会将SQL Server的bigint转换为小数,须手动调整为Access的整型或长整型;
5、索引。转换程序不会转换索引,需手动在Access中建立索引。

在Delphi/bcb下,想让程序同时支持Access及SQL Server,需注意以下方面:

1、 在Access中使用 SELECT * FROM Books WHERE RegDate = ‘2007-5-1′ 是会出现“标准表达式中数据类型不匹配”这样的错误的(RegDate是日期型),必须使用SELECT * FROM Books WHERE RegDate = #2007-5-1# 或 SELECT * FROM Books WHERE RegDate = CDate(’2007-5-1′);
但在Access中,Insert、delete和update中使用单引号界定日期却是可以正常执行的。
2、尽量不要使用SQL Server的bigint类型,尤其该字段是自增的情况下;
3、Access的varchar(文本)型最大只有255,所以如果一个文本型字段大于255时,最好定义成备注型(Access中)或text型(SQL Server中);
4、在Access中一般会出现如下错误:不正常地定义参数对象,提供了不一致或不完整的信息。将相应Query的ParamCheck设为False即可;
5、Access中的逻辑值在库中为-1和0,而SQL Server中为1和0,所以写BoolField = 1这样的语句有兼容性问题,应该改为BoolField <> 0;
6、在Access中有主键的Query才可更新,而SQL Server无此要求。