delphi中sql嵌套赋值的问题

秋天之落叶 2024-02-06 15:22:07

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.

我哪里写的有问题呢?请高手指教。

...全文
422 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
crazy_boom 05-03
  • 打赏
  • 举报
回复

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子句中多重赋值如果有依赖关系,结果是实现相关的,不同的数据库系统可能有不同的结果,所以不要写这样的代码~

  • 举报
回复 1
@日立奔腾浪潮微软松下联想 请教应该怎么写?是分开写,还是另有别的方法?
@秋天之落叶 用嵌套的update应该可以
  • 举报
回复 1
@日立奔腾浪潮微软松下联想 嵌套的update?update table set a=A from T1 where m=n,b=…这样写?
2条回复
  • 打赏
  • 举报
回复

另外我想问一下
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正确结果。

  • 举报
回复
@秋天之落叶 完成后,a*b星号都不显示了?上面怎么可以?
BlueStorm 02-08
  • 打赏
  • 举报
回复

我用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;
BlueStorm 02-08
  • 举报
回复
@BlueStorm Provider选择的是Microsoft OLE DB Driver for SQL Server
  • 举报
回复
@BlueStorm 我试了两个连接串,你的这个和sql server native client 11.0都不行,研究了一下,可能和我的流程有关: adoconnetion.begintrans; insert into 新表 from 表1,表2 //在事务中,这个 新表 是不是已经形成? update 新表 set a=b*c,b=e*f adoconnetion.committrans; 是不是在事务中,字段计算的前后值会有影响,或者说 没有实值的形成前不能 嵌套计算? 整个系统还有一个地方也是这样,一会我试一下,看看在没有事务的流程里是不是可以。
  • 举报
回复
@BlueStorm 理论上你的和我的应该是一样的,但是,我的结果确实很奇怪,目前还在懵逼中
  • 打赏
  • 举报
回复

我查询到的
(1)MySQL的update语句,set列的顺序是有关系的,后面列的计算是以前面列的结果为基础的,即从左向右评估;
(2)SQLServer的update语句,set的顺序无关,所有的更改都是基于之前取出的快照;

  • 打赏
  • 举报
回复

难道在sql的直接执行环境中有优化的成分?

  • 打赏
  • 举报
回复

set列的顺序是有关系的,后面列的计算是以前面列的结果为基础的,即从左向右评估。先计算a的值,此时b默认值应该为0.

  • 举报
回复
@borland56755 我想到这个问题了,但是在sql2014版本下,直接执行sql语句是没有问题的,delphi传过来的语句执行就不行,除了拆成两个语句,有其他办法解决吗?
  • 举报
回复
@borland56755 在delphi中写成update 表 set b=e*f,a=b*c 也不行

5,702

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧