5,702
社区成员
sql环境下
update 表 set a=b*c,b=e*f
条件成立,计算正确。
为什么这个语句写在delphi中就不能正确执行,必须要分开写;
ado.sql.text:='update 表 set b=e*f';
ado.sql.text:='update 表 set a=b*c';
才可以正确执行,否则a就等于0.
我哪里写的有问题呢?请高手指教。
ado.close;
ado.sql.text:='update 表 set b=ef,a=bc ' ;
ado.execSql;
这样执行的内容和 在sql 中执行的结果是一样的
看来借用计算结果再计算的问题确实存在,sql语句不是递归计算的,没有好的办法,一是分开写,二是重复使用已经有的数据
set x=ab,y=xef,m=cd,n=mgh
写成
set x=ab,y=abef,m=cd,n=cdgh
就没问题了。
暂时先这样处理了。
什么叫做“计算正确”?
set子句中多重赋值如果有依赖关系,结果是实现相关的,不同的数据库系统可能有不同的结果,所以不要写这样的代码~
另外我想问一下
Microsoft OLE DB Driver for SQL Server
sql server native client 11.0
两个有什么差别吗?
测试结果:
1、源程序代码中,关闭事务,还是insert+update还是不行,a=0。
2、同样的update语句,拿在事务之外,不用insert形成新表,直接用新表的数据,静态处理update嵌套赋值就没有问题,在事务中update多个值且前后有赋值关系的,就取不到相应的值。
3、利用断点测试,insert新表后中断运行,然后在sql环境下用update,奇怪的一幕出现了,(我是set四个字段,前两个计算结果被后两个分别使用)第一次update,第一个第三个数修改了,第二个使用第一个结果的和第四个使用地算个结果的,没有变化,第二次update神奇的一幕出现了,第二个数第四个数也修改正确了。
这个有点懵逼了,不是事务影响的结果,insert+update不就是静态的处理新表的数据吗?为什么要两次才能出正确结果?
有遇到类似情况的吗?
表结构如下:
insert新表字段 a b c d e f g h为浮点值,有有效数值,x y m n均为0
update 新表 set x=ab,y=xef,m=cd,n=mgh
第一次update后x和m有正确结果,y和n还是0;第二次update后,y和n正确结果。
我用Delphi 10.3.3+sqlserver 2014测试了一下,没发现你说的问题
不管是update test2 set a=bc,b=ef, 或者是update test2 set b=ef, a=bc, 结果完全一样.
create table test2 (a int, b int, c int, e int, f int)
insert into test2 values (1,2,3,4,5)
两者的Delphi程序执行结果都是(6,20,3,4,5), 跟sql环境完全一致.
Delphi程序操作数据库本质就是向数据库服务器发送sql语句, 你可以通过SQL Profiler查看Delphi程序发给sql数据库服务器的语句是什么.
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
//ADOQuery1.SQL.Text := 'update test2 set b=e*f, a=b*c';
ADOQuery1.SQL.Text := 'update test2 set a=b*c, b=e*f';
ADOQuery1.ExecSQL;
end;
我查询到的
(1)MySQL的update语句,set列的顺序是有关系的,后面列的计算是以前面列的结果为基础的,即从左向右评估;
(2)SQLServer的update语句,set的顺序无关,所有的更改都是基于之前取出的快照;
难道在sql的直接执行环境中有优化的成分?
set列的顺序是有关系的,后面列的计算是以前面列的结果为基础的,即从左向右评估。先计算a的值,此时b默认值应该为0.