MySQL:在SELECT语句中使用变量

3
请查看以下声明。
INSERT INTO Ongoing_Fees (currentDate, Gross_Fee, Insurance_Fee, Submit_Fee)
    SELECT current_timestamp, New.Gross_Fee,
           @InsuranceFee := (New.Gross_Fee)*(p.E_Fee/100),
           @SubmitFee := @InsuranceFee-(p.s_Fee/100)
    FROM Portfolio p
    WHERE p.idPortfolio = New.idPortfolio;

在这里,我使用了两个用户定义变量@InsuranceFee@SubmitFee。正如您所看到的,您可以通过从@InsuranceFee中减去一个值来获得@SubmitFee

现在,为了使这个工作正常,@InsuranceFee"必须"首先进行评估。然而,MySQL文档如下所述:

通常情况下,除了在SET语句中之外,不应在同一语句中将值赋给用户变量并读取该值。例如,要递增一个变量,可以这样做:

SET @a = @a + 1; 对于其他语句,比如SELECT,你可能会得到你期望的结果,但这并不是保证的。在下面的语句中,你可能认为MySQL会首先计算@a,然后进行第二次赋值:

SELECT @a, @a:=@a+1, ...; 然而,涉及用户变量的表达式的计算顺序是未定义的。

那么,在SELECT内部使用变量的最佳方法是什么?

更新

也许首先使用单独的SELECT语句将值分配给变量更好?像下面这样...

 SET   @InsuranceFee :=    New.Gross_Fee * ((SELECT E_Fee FROM Portfolio WHERE idPortfolio = New.idPortfolio)/100);

 SET   @SubmitFee := @InsuranceFee - ((SELECT s_FeeFROM Portfolio WHERE idPortfolio = New.idPortfolio)/100)

    INSERT INTO Ongoing_Fees (currentDate, Gross_Fee, Insurance_Fee, Submit_Fee)
           current_timestamp, New.Gross_Fee,
                   @InsuranceFee ,
                   @SubmitFee

在这种情况下使用9.4用户定义变量是不安全的,我将寻找新的选项(也许使用13.6.6游标)来达到目标。 - wchiquito
在这种情况下,为什么需要使用“用户定义变量”?只需使用(New.Gross_Fee)*(p.E_Fee/100)-(p.s_Fee/100)即可。 - sgeddes
@ sgeddes:您是否愿意使用类似于 ((New.Gross_Fee)*(p.E_Fee/100))-((((New.Gross_Fee)*(p.E_Fee/100))*(p.I_Fee/100))+(((New.Gross_Fee)*(p.E_Fee/100)-(((Gross_Fee)*(p.E_Fee/100))*(p.I_Fee/100)))*0.2)) 这样的东西。这是我的真实查询内容... - PeakGen
@wchiquito:请检查我的更新。 - PeakGen
正如您在以下SQL Fiddle中所看到的,您的选择是完全有效的,但是您的选择必须对Portfolio表执行两个查询。@sgeddes提出的解决方案可以在单个子查询中获取两个值,并避免使用9.4用户定义变量,正如您在以下SQL Fiddle中所看到的那样。 - wchiquito
1个回答

0

用户定义变量不应该像这样使用。如我在评论中提到的,没有理由不把所有内容都写出来。然而,如果你只是喜欢临时语法,你可以使用子查询:

INSERT INTO Ongoing_Fees (currentDate, Gross_Fee, Insurance_Fee, Submit_Fee)
SELECT ct, gross_fee, InsuranceFee, InsuranceFee-SubmitFee
FROM (
    SELECT current_timestamp ct, 
       New.Gross_Fee,
       New.Gross_Fee*p.E_Fee/100 as InsuranceFee,
       p.s_Fee/100 as SubmitFee
    FROM Portfolio p
    WHERE p.idPortfolio = New.idPortfolio
) T

@Sniper -- 为什么你要运行3个SQL语句,当你可以用一个语句完成所有操作呢?你有其他的要求需要使用“用户定义变量”吗?子查询是更好的方法,可以利用临时值。话虽如此,在我看来,把所有内容都写出来也没有问题。 - sgeddes
没有错,但是超级难编辑。例如,我在评论中提供的查询,您可以轻松编辑吗?除此之外,我们有许多地方需要使用条件,例如“如果该记录不存在,则值为0,否则为1”等等。当您有3-4个类似的条件时,一次性编写可能不是问题,但如果出现问题,除非使用变量清晰地编写,否则将很难阅读和编辑。 - PeakGen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接