如何在MySQL中声明变量?


386

如何在mysql中声明变量,以便我的第二个查询可以使用它?

我想写一些像:

SET start = 1;
SET finish = 10;

SELECT * FROM places WHERE place BETWEEN start AND finish;

别忘了,您可能需要“允许用户变量= True”。
史蒂夫·史密斯,

Answers:


636

MySQL中主要有三种类型的变量:

  1. 用户定义的变量(以开头@):

    您可以访问任何用户定义的变量,而无需对其进行声明或初始化。如果引用的变量尚未初始化,则其值为NULL和字符串类型。

    SELECT @var_any_var_name

    您可以使用SETSELECT语句来初始化变量:

    SET @start = 1, @finish = 10;    

    要么

    SELECT @start := 1, @finish := 10;
    
    SELECT * FROM places WHERE place BETWEEN @start AND @finish;
    

    可以从一组有限的数据类型中为用户变量分配一个值:整数,十进制,浮点数,二进制或非二进制字符串或NULL值。

    用户定义的变量是特定于会话的。也就是说,一个客户端定义的用户变量不能被其他客户端看到或使用。

    可以SELECT使用高级MySQL用户变量技术在查询中使用它们。

  2. 局部变量(无前缀):

    局部变量需要在使用DECLARE之前声明。

    它们可用作存储过程内的局部变量和输入参数:

    DELIMITER //
    
    CREATE PROCEDURE sp_test(var1 INT) 
    BEGIN   
        DECLARE start  INT unsigned DEFAULT 1;  
        DECLARE finish INT unsigned DEFAULT 10;
    
        SELECT  var1, start, finish;
    
        SELECT * FROM places WHERE place BETWEEN start AND finish; 
    END; //
    
    DELIMITER ;
    
    CALL sp_test(5);
    

    如果DEFAULT缺少该子句,则初始值为NULL

    局部变量的范围是BEGIN ... END在其内声明的块。

  3. 服务器系统变量(以前缀@@):

    MySQL服务器维护许多配置为默认值的系统变量。它们可以是类型GLOBALSESSIONBOTH

    全局变量影响服务器的整体操作,而会话变量影响单个客户端连接的服务器操作。

    要查看正在运行的服务器使用的当前值,请使用SHOW VARIABLES语句或SELECT @@var_name

    SHOW VARIABLES LIKE '%wait_timeout%';
    
    SELECT @@sort_buffer_size;

    可以在服务器启动时使用命令行或选项文件中的选项来设置它们。其中的大多数可以在服务器运行时使用SET GLOBAL或动态更改SET SESSION

    -- Syntax to Set value to a Global variable:
    SET GLOBAL sort_buffer_size=1000000;
    SET @@global.sort_buffer_size=1000000;
    
    -- Syntax to Set value to a Session variable:
    SET sort_buffer_size=1000000;
    SET SESSION sort_buffer_size=1000000;
    SET @@sort_buffer_size=1000000;
    SET @@local.sort_buffer_size=10000;

3
=运营商不知何故对我不起作用。当我使用:=运算符时,它工作正常。
divinedragon 2014年

24
=运算符仅在SET子句中起作用。要为SELECT查询中的变量赋值,可以使用:=运算符,例如SELECT @start := 1
Omesh 2014年

2
您能否说明这是什么意思:“无需声明用前缀@表示的用户定义的会话变量”?
billynoah 2015年

3
@billynoah我假设这意味着用户定义的Session变量(以@开头)不需要显式声明;您可以立即将它们分配给它们,就好像它们已经被声明一样。
jobo3208 2015年

2
您可以使用以下select语句的结果分配一个变量:SET @subscriptionId =(从User中选择subscriptionId,其中emailAddress='ac@tmail.com');
软件先知

28

SET @var_name = value 

要么

SET @var := value

运算符=:=都被接受


选择

SELECT col1, @var_name := col2 from tb_name WHERE "conditon";

如果发现多个记录集,则仅col2中的最后一个值是keep(覆盖);

SELECT col1, col2 INTO @var_name, col3 FROM .....

在这种情况下,select的结果不包含col2值


两种方法都使用

-TRIGGER_BEFORE_INSERT ---从计算中设置列值

...
SELECT count(*) INTO @NR FROM a_table WHERE a_condition;
SET NEW.ord_col =  IFNULL( @NR, 0 ) + 1;
...

3
=和之间有什么区别:=
Koray Tugay

2
我猜想对于mysql SELECT语法,必须将=(比较)的含义与:=(赋值)
分开

1
在某些情况下,变量中剩余的值可能与返回的最后一行不对应。例如,SELECT DISTINCT IFNULL(@var:=Name,'unknown') FROM Customers ORDER BY <some non-indexed expression> LIMIT 10似乎在order-by完成之前评估变量分配,以便@var的返回值甚至可能与任何返回的行都不相关。不过,文档并未说明在什么条件下会发生这种情况。
Doin


3

不同类型的变量:

  • 局部变量(不带@前缀)是强类型化的,并且作用域范围是声明它们的存储程序块。请注意,如DECLARE语法中所述

仅在BEGIN ... END复合语句内部允许使用DECLARE,并且必须在其开始处以及其他任何语句之前。

  • 用户变量(以@开头)是松散类型的,并且作用域为会话。请注意,它们既不需要也不能声明,只需直接使用它们即可。

因此,如果您正在定义一个存储程序,并且确实想要一个“局部变量”,则需要删除@字符,并确保DECLARE语句位于程序块的开头。否则,要使用“用户变量”,请删除DECLARE语句。

此外,为了将其作为子查询执行,您将需要用括号将查询括起来:

SET @countTotal =(从nGrams中选择COUNT(*));

否则,您可以使用SELECT ... INTO:

从nGrams中选择COUNT(*)到@countTotal;


1

对于在concat_ws函数中使用@variable来获取串联值的任何人,请不要忘记使用空值重新初始化它。否则,它可以将旧值用于同一会话。

Set @Ids = '';

select 
  @Ids := concat_ws(',',@Ids,tbl.Id),
  tbl.Col1,
  ...
from mytable tbl;

0
  • 宣布: SET @a = 1;

  • 用法: INSERT INTO `t` (`c`) VALUES (@a);


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.