Delphi与SQL Server6.5的Text字段,到底谁的错?(100分)

  • 主题发起人 主题发起人 Jao
  • 开始时间 开始时间
J

Jao

Unregistered / Unconfirmed
GUEST, unregistred user!
我用Delphi写了一个ISAPI,SQL Server6.5做后台数据库。在其中有一条SQL语句:
Insert mTable(mField) Values(:mField) {mField是一个Text字段}
然后用
Query.ParamByName('mField').AsString := 一个长度大于255的字串;

结果发现一个奇怪的问题:

1、当向一个Text字段insert一条记录时,发现只要长度大于255的字符都会变成乱码。而直接在SQL的Enterprise Manager中向数据库中insert记
录,虽然没有乱码,但是后面的字符全部被砍掉了。

2、如果用一个TDBMemo向表中直接写入这个长串,则没有任何问题,说
明SQL Server的Text字段应该没Bug;

3、在ISAPI中Debug这个Query.ParamByName('mField').AsString,其中的
内容没有问题,说明错也不在Delphi;

这就怪了,谁都没错,难不成只有我错了?请大家帮忙看看怎么回事?
 
用Query.ParamByName('mField').AsMemo 行不行?
 
cAkk:
AsString本身绝对没问题!
我最近写的那个论坛,帖子内容也是用AsString写入的

实际上,因为Delphi的长字符
1、支持2G字节容量
2、本身有长度记数,因此可包含任何内容
所以任意类型的BLOB字段都可以以AsString来读/写

TDBBackup中遇到BLOB字段一律用AsString读写,你注意到了么?
AsString是不用怀疑的

Jao:
我现在倒怀疑ParamByName的使用上有问题
你不妨试一下:
<font color=red>with Query do
begin
Close;
SQL.Text:='Select * from mTable'
+' Where 1<>1';
Open;
Insert;
FieldByName('mField').AsString:=xxx;
Post;
end;</font>
如果可以成功,就先这么干吧!
老实说,我也是这么干的~~~

<B>问题出在哪里,我也不清楚</B>,以后再研究

不过用Text类型可能导致的问题有:
1、字符串中包含引号时需要小心处理
2、字符串中包含非法字符(比如半个汉字)时,可能截断SQL语句的后半部分
所以我从来不敢用Insert语句直接插入Text类型字段
用Image字段就不会有这种麻烦
因为SQL语句是写成:
...
values(....,0xbc2332....)
直接用16进制
 
蚯蚓:
在用sql语句更改数据的时候,也就是说用parambyname的时候,<b>asstring确实
有问题</b>,不能用来赋值memo类型的字段,<b>似乎</b>是sql语句本身的限制,
因为多行的文本在sql语句里面<b>似乎</b>是不被允许的.

你的语句是正确的,fieldbyname可以使用多行的string,而且这也是目前我知道
的唯一的修改memo类型字段的方法,实际上我也是这么用的.

其实我早就注意过这个问题,你知道我怎么开始注意的吗? 很长时间以前,我曾经
准备用CGI/ISAPI做一个和"大富翁"一模一样的论坛,于是我查阅yysun的asp
源代码,发现他在保存大家发言的时候,用的是:
recordset.edit;
recordset('username')=...;
recordset('datetime')=...;
recordset('content')=...;
....
recordset.update;
类似这样的方法.

当时我觉得非常奇怪: 为什么不用一个insert的sql语句一次搞定呢?
于是我自己做,决定只用一个sql语句来搞定,结果可想而知,和Jao遇到
的情况一样,于是我才明白yysun这样添加纪录的缘由.

当然,也许有更好的办法,但我目前知道的只能这样做,无法在sql语句里面实现.
 
cAkk:
sql语句中用多行文本应该是允许的,起码在Oracle上没有任何问题。
以前我也用delphi处理过留言本,没用碰到问题,记得当时用的是:
with Query do
begin
SQL.Text := 'insert into book_comment '+#13+#10
'values ('+ comment + ','+#13+#10 +
user_id + ','+#13+#10 +
……
ExecSQL;
end;
虽然有点丑陋,但是用着没问题。但是我不敢肯定Oracle以外的数据库,
或者是通过ODBC连接的Oracle是不是也能这么写
 
dssn: 你试过把sql语句里面的一个变量分几行写吗? 比如你的例子:
with Query do
begin
SQL.Text := 'insert into book_comment '+#13+#10
'values ('+<b> 'abcdefg
hijklmn
opqrst'</b> + ','+#13+#10 +
user_id + ','+#13+#10 +
……
ExecSQL;
end;

肯定不行吧? 我的意思就是: 如果你的comment是一个多行文本,sql语句<b>可能</b>
不能接受.
 
谢谢大家!
我用cAkk的方法试了一下,ParamByName().AsMemo暂时解决了问题。但是对这个
问题十分不解。
cAkk,SQL语句对多行文本应该没有限制,至少在Enterprise Mangager中Insert
一条多行文本不会有问题,说明SQL<b>本身</b>没有限制。

查了一下资料,发现SQL Server的Text字段缺省显示255个字符,
最大固定分配空间为2K,再大的空间就要动态分配。我想是否因为AsString和
AsMemo对字串的存储方式不同而引起以上问题?

这个问题很有意思。我想多留几天,大家讨论一下。
 
首先请注意我所谓的"多行文本",并不是"多行SQL语句".

如果是多行的sql语句,我想数据库引擎是能够知道应该合并成一行的,但是,如果
是sql语句中的一个变量被拆分成多行,可能数据库引擎是无法合并的---仅仅猜测.

比如某一个字段叫comment,是一个text类型的变量,那么下列语句是没问题的:
update tablename
set comment='abcdefg'
但是同样是多行,下面语句就可能有问题:
update tablename set comment='abcd
efg'

上面是2种不同情况的多行,第一种符合语法规范,应该被接受,第2种恐怕不能被接受.

以上仅是我的猜测.



 
小弟在使用MYSQL的过程中并没有如此的问题,但在DELPHI的系统下
就好象有了。
小弟的猜测是:其实字符串里面可以包含任何ASCII码,但如果写在
DELPHI的编译器上的话,就可能出问题了,因为DELPHI来帮你处理
了那些特殊的ASCII码罗!能不能使用转义符号来做呢?
在C语言下小弟不但能这样传文本,还能传图片等信息,但就需要“躲
过”DELPHI的处理。一个简单但效率不高的办法是全转成ASCII的内码,
所有信息以ASCII数字码传送,另一个复杂点的就用INTERNET的QUERY STRING
方法,把特殊的字符变成%XX来传,总之对标准0-128的ASCII码,DELPHI
和SQL都肯定支持的。
 
多行文本肯定是可以的,
cAkk请注意,我的例子里多行文本是放在一个变量中的(其中有回车换行).
你写的有重大的区别,因为delphi编译器不允许字符串跨行
我的例子使用在一个网上书店中,用于纪录用户书评,正在正常使用中
所以说应该没有问题
 
>>我的例子里多行文本是放在一个变量中的(其中有回车换行
老兄,你的变量在执行的时候就变成字符串了,如果里面有回车的话,
效果就和我举的例子一样.
 
cAkk
请你先试一试我的写法,是不是如你所说真的不行,
谢谢!!
 
多人接受答案了。
 
文本不能使用insert 语句,请查看sql
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部