兼容mysql
(创建时间:2012年09月28日 19:23:00)
Jangogo : 

SC 环境增加 一个常数  DBT_ ="access"  '表示当前数据库的类型, 枚举: access, sqlserver, mysql

SC 环境增加一个函数 function ST_(s) 这个函数用于不同数据库的Select Top 语句的兼容.

     如果你的 sql 语句里面包含了 select top n ..., 你必须把你的 语句用ST_函数处理一下, 如:

     sql="select Top 10 * from ac"

     sql=ST_(sql)  ' 这时如果数据库类型为MySQL 则 sql 变成 "select * from ac LIMIT 10"
     注意, 如果你的SQL语句里面有多个TOP关键字,你必须把SQL语句拆分成单独的只包含一个top 关键字的语句后再合并.

     如果你的 sql 语句包含了 字符串字段的 链接如: select acid + '   ' + actitle from ac 也请使用ST_函数.

     因为mySQL 不支持使用 + 加号来进行字符串链接, 字符串链接MySQL是使用concat 函数, ST_会在内部进行帮你转换(需要升级平台到2012.10.20之后的版本).

     注意ST_函数的一下局限:

     1. ST_只能处理 第一个Select 后的内容, 如果有Select嵌套,则需要先用ST_处理后再嵌套,例如:

         SQL=ST_("select * from (select top 10 * from ac)") 这样是无效的,应该改为:

         SQL="select * from (" & ST_("select top 10 * from ac")  &  ")")

        

         SQL="select * from (select acid +' ' + actitle from ac)" 也应该参照上一句来更改         

 

     2. 为了避免 concat 转换时候, 数字类型的相加混淆 , ST_只会对包含有单引号的字段部分进行concat转换处理

         例如: SQL=ST_("select acid,acptitle + actitle from ac") 这样的结果是sql语句不会改变, 你必须更改为:

                  SQL=ST_("select acid, ''+acptitle + actitle from ac"), 这样ST_才会认为''+acptitle + actitle 需要concat处理

 

SC 环境修改了GetRS_() 函数,在内部增加了:

  if lcase(DBT_="mysql") then

      GetRS_.CursorLocation=3

  end if

  一下问题中如果牵涉到  CursorLocation的,均已经由平台统一处理,但是必须注意:

  A.  SC虚拟机(即SC环境,)必须是最新2012-10-15以上版本的, http://www.4Fang.net/4ff/sc_setup.exe 下载更新

  B.  必须通过 GetRS_() 来获得Recordset对象

 

 

1.识别符
mysql识别符是 ``;sql server识别符是[].
mysql下表名或者字段名用[]包围,都会出错。例如:
create table [tbl] (id int);
alter table tbl add [f1] text;

***解决方式: 在SQL语句中避免使用 "[]" 来包裹字段名和表名, 如果字段名和表名是关键字, 必须区别不同的数据库对待

 

2.定义自增字段
mysql定义自增字段用 auto_increment;sql server用indentity(1,1)

***解决方式:增加字段时, 必须区分不同的数据库书写不同的SQL语句

3.注释
mysql注释符 -- comments,注释内容和注释符号要留个空格,不然没有注释效果(命令行界面下验证);sql server注释符与注释内容间有无空格皆可。如 --comments  -- comments

***解决方式: 统一使用注释内容和注释符号之间多留一个空格的兼容方式

 

4.取字符串长度函数
mysql用length(str);sql server用len(str)

***解决方式: 已经通过mysql的自定义函数统一一次性解决,编程人员可以不理会,直接使用 len() 函数即可


5.数据类型text 整类型unsiged
mysql的text数据类型,有65KB的存储空间,longtext有4G存储空间;sql server的Text数据类型有2G存储空间。
mysql的整型数据类型可以指定unsigned,获得更大的取值范围。如 amount int unsigned
***解决方式: 我们统一使用text就可以了,除非我们可以预见某个字段数据量超过65K,则使用longtext类型


6.增加多个字段
mysql要加括号
包围字段列表 例如:
  MS sql:alter table t add f1 int,f2 int,f3 int;

  Mysql: alter table t add (f1 int,f2 int,f3 int);

***解决方式:必须按不同数据库的要求进行区分书写, 没有兼容的方式


7.like子句
  Mysql select ...like,like 子句不支持[0-9]这样的匹配方式,它有扩展正则表达式子句 rlike 支持 . * [] ^ $ {n}等元字符。

  Ms sql: select * from teacher where tname like 'C[0-9][0-9]'; -- 没问题,可以匹配到 C02 C29 ...  Mysql: select * from teacher where tname like 'C[0-9][0-9]'; -- 不会出错,但是like会认为要匹配字符串 C[0-9][0-9] 所以没结果返回  Mysql: select * from teacher where tname rlike '^C[0-9]{2}$'; -- rlike子句的等价写法

***解决方式: 区别数据库对待, 这种情况我们极少用到,只在basedatacommon中用到


8.rs.recordCount
ado连接mysql,sql server数据库,打开rs对象默认的游标位置都是服务端游标。
sql server: rs.open "select * from company",cn,1,1  -- rs.recordCount返回正确的记录数
sql server: rs.open "select * from company",cn,1,1  -- rs.recordCount返回-1,解决方法:在rs.open之前 设置 rs.cursorLocation=3  或rs.cursorLocation=aduseClient。注:cursorLocation在记录集打开之前是可读可写的。打开记录集后为只读。可通过connection对象或recordset对象设置 如:cn.cursorLocation=3, rs.cursorLocation=3

***解决方式:碰到这种问题,把改成rs.cursorLocation=3

9.rs.addnew ....rs.update问题
如product表有数据如下:
Pname
产品A
产品B

SC页面:
rs.open "select * from product" cn,1,3
rs.addnew
rs("Pname")="产品C"
rs.update
response.write rs("Pname")  '结果显示 产品B 而不是新记录的值

***解决方法:rs.open语句前设置游标位置为客户端游标 rs.cursorLocation=3

若用循环语句批量增加记录数很多 例如超过80条,如:
rs.open "select * from product" cn,1,3
for i=1 to 200
rs.addnew
rs("Pname")="产品"&i
rs.update
next

***解决方式:设置客户端游标后还是会有部分记录不能增加进去的情况,这时应把设置lockType=4,rs.update改用rs.updateBatch

10.rs.update多条记录的问题
同样是product表,更新一条记录马上去更新的值没问题;通过循环更新多条记录,就马上取更新后的值有问题。
rs.open "select * from product" cn,1,3
rs("Pname")=rs("Pname")&"modified" '游标位于第一条记录
rs.update
response.write rs("Pname")  '结果为修改后的新值

更新多条记录的情况:
rs.open "select * from product" cn,1,3
do while not rs.eof
rs("Pname")=rs("Pname")&"modified" '游标位于第一条记录
rs.update
rs.movenext
loop

response.write "<h2>更新后的结果</h2><br>"
rs.movefirst
do while not rs.eof
response.write rs("Pname")&"<br>"
loop
'此时显示的是更新前的数据

***解决方法:在rs.open语句之前,设置为客户端游标 rs.cursorLocation=3

 

11. select count(*) from mytable 返回的记录的值的数据类型是VBS不能识别的, 必须用Clng函数强制转换后才能进行运算和比较:

 

     rs.open "select count(*) from mytable",cn

     if rs(0)>0 then    ''这样会导致VBS引擎崩溃 应该改成:

     if clng(rs(0))>0 then

 

 12. 使用记录集修改操作

   

   打开记录集的语句如为 sql = " select invoiceitem.lo as lo  from invoice,invoiceitem where invoice.id = invoiceitem.iid "

    rs.open sql,cn,1,3

    rs("lo") = 2

    rs.update

 

   这种情况下将会报出 "缺少更新或刷新的键列信息" 错误,如是有主外键关系的请使用 inner join 语句联接打开需要修改的记录集

   sql = "select invoiceitem.lo as lo from invoice inner join invoiceitem on invoice.id = invoiceitem.iid "

 

 13 .mysql判断字段是否存在有简单的方法 只需要 rs.open "describe yourtbl yourFiled" ,cn,1,3
      if not rs.eof then 字段存在

 

文档中心
可上传附件
选择
同时转发此条
回复
1楼
Jangogo: 
tpl表moudle字段的特殊处理 因为 moudle 在 access数据库是 关键字, 在SQL语句里面必须使用 中括号 包裹 [module] 但是 mysql 不能使用 中括号 来包裹关键字, 因此使用以下解决方法: 考虑到 基本上使用 tpl表 module 字段的情况下都会引用 xcell.sc.asp , 因此更改 xcell.sc.asp  增加…【更多】