mysql中如何定义变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql中如何定义变量相关的知识,希望对你有一定的参考价值。

SELECT @myRight := rgt FROM nested_category WHERE name = 'TELEVISIONS';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myRight;
mysql中能不能实现类似的功能,定义变量,然后再后面的sql语句中使用。谢谢各位了

测试一下, 好像是可行的呀!

mysql> select @test := 1;
+------------+
| @test := 1 |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

mysql> select * from test_main;
+----+-------+
| id | value |
+----+-------+
|  1 | ONE   |
|  2 | TWO   |
|  3 | THREE |
+----+-------+
3 rows in set (0.00 sec)

mysql> select * from test_main where id > @test;
+----+-------+
| id | value |
+----+-------+
|  2 | TWO   |
|  3 | THREE |
+----+-------+
2 rows in set (0.00 sec)

参考技术A 一、局部变量
局部变量一般用在sql语句块中,比如存储过程的begin/end。其作用域仅限于该语句块,在该语句块执行完毕后,局部变量就消失了。
局部变量一般用declare来声明,可以使用default来说明默认值。
二、用户变量
用户变量的作用域要比局部变量要广。用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。
用户变量使用如下(这里我们无须使用declare关键字进行定义,可以直接这样使用):
select @变量名
对用户变量赋值有两种方式,一种是直接用"="号,另一种是用":="号。其区别在于使用set命令对用户变量进行赋值时,两种方式都可以使用;当使用select语句对用户变量进行赋值时,只能使用":="方式,因为在select语句中,"="号被看作是比较操作符。
参考技术B MySQL 变量存在的介质及意义:

MySQL 的变量存在于内存、以及配置文件中;
其中内存中的变量是在运行时生效,配置文件中的变量是在 mysqld 程序启动时加载到内存中;

MySQL 8 版本以前为了保证修改后的变量的值在 MySQL 运行时及 MySQL 重启后生效,此时你需要分别修改内存和配置文件中变量的值:
SET global/session 语句设置内存中全局/当前会话的变量的值,通过 Linux 命令⼿⼯修改配置⽂件中变量的值,此时你会发现,你的配置⽂件需要 通过 ps -ef | grep mysql 查看进程启动命令中带⼊的选项 --defaults-file,以确定配置⽂件,如果启动命令没有带⼊选项 --defaults-file,那么默认配置⽂件为 /etc/my.cnf ;
你会发现修改配置⽂件时,需要确定配置⽂件,以及修改配置⽂件,这个步骤其实蛮繁琐的,⽽且如果你⼀不小心写错了变量名或值,可能会直接导致启动 MySQL 失败,如果此时 你有其他策略依赖 MySQL 的启动/重启,那么这个 MySQL 启动失败可能⼜会导致你策略判断不符合预期,造成其他不好的后果,这可能是就是亚马逊飓风初始的那只蝴蝶的翅膀。

如何根据 HTML FORM 中定义的变量动态生成 MYSQL UPDATE 语句

【中文标题】如何根据 HTML FORM 中定义的变量动态生成 MYSQL UPDATE 语句【英文标题】:How to dynamically generate MYSQL UPDATE statement based on defined variables from HTML FORM 【发布时间】:2014-10-30 06:46:24 【问题描述】:

我正在使用一个相当长的 HTML 表单来更新与产品相关的许多详细信息 - 为简洁起见,我不会完整地分享该表单。但是,出于说明目的,这里有一个 sn-p :

HTML 表单

<form name="form1" method="post" action="update_ac.php">
    <table  cellpadding="0" cellspacing="0">
    <tr>
      <td>
        <input name="season" type="text"  class="button_select" id="season" value="<?=$rows['season']; ?>" size="10" />
        <input name="restock" type="checkbox" id="restock" value="on" <?php if($rows['restock']=='on')  echo 'checked="checked"';  ?>/>

      // other fields

      </td>
    </tr>
  </table>
</form>

我的问题是在将表单发布到update_ac.php 时 - 如何根据已完成的字段动态生成 MYSQL 更新语句?

这是我的表单操作页面的示例:

PHP 表单操作

<?php

       foreach ($_POST as $key => $value) 
        $$key = $value;
      

$sql= mysql_query ("
UPDATE product SET
title='".$title."',
rating='".$rating."',
season='".$season."', 
brand_id='".$brand_id."',
category='".$category."', 

... etc ");

?>

我不想在 UPDATE 语句中声明每个可能需要更新的字段。鉴于存在从表单发布的已定义 PHP 变量,我希望 UPDATE 语句仅处理相关字段。

目前,我收到很多NOTICE: Undefined variable x,在发布表单时出现了空白字段。

我希望这是有道理的——有点啰嗦。

有什么建议吗?谢谢

更新

从@Styphon 的回答开始 - 我稍微修改它以在查询末尾包含WHERE 条件。

$query = "UPDATE product SET";
$comma = " ";
foreach($_POST as $key => $val) 
    if( ! empty($val)) 
        $query .= $comma . $key . " = '" . mysql_real_escape_string(trim($val)) . "'";
        $comma = ", ";
    


$product_id = $_POST['product_id'];

$query = $query . "WHERE product_id = '".$product_id."' ";

【问题讨论】:

看看isset 或许> @Fluffeh - 这并不能解决我的问题,因为我必须针对 ISSET 测试每个可能的变量。我试图避免声明超过 50 个变量。 【参考方案1】:

假设表中的所有字段名称都与表单输入的名称相同,这是直截了当的。你可以使用这个:

$query = "UPDATE product SET";
$comma = " ";
foreach($_POST as $key => $val) 
    if( ! empty($val)) 
        $query .= $comma . $key . " = '" . mysql_real_escape_string(trim($val)) . "'";
        $comma = ", ";
    

$sql = mysql_query($query);

为了更安全,您应该创建一个可接受参数的白名单,即表中的列如下:

$query = "UPDATE product SET";
$comma = " ";
$whitelist = array(
    'title',
    'rating',
    'season',
    'brand_id',
    'cateogry',
    // ...etc
);
foreach($_POST as $key => $val) 
    if( ! empty($val) && in_array($key, $whitelist)) 
        $query .= $comma . $key . " = '" . mysql_real_escape_string(trim($val)) . "'";
        $comma = ", ";
    

$sql = mysql_query($query);

这样您的查询只能包含您设置的参数,并且如果有人设法注入额外内容(例如通过更改表单输入的名称),它将不会被传递到您的数据库。


我还建议你停止使用 Mysql_*,它是 deprecated。您应该查看 MySQLi 或 PDO 作为替代方案。

【讨论】:

@nalply 我在real_escape_string里加了,现在太习惯用prepared statements了。 @Styphon - 我刚刚意识到声明末尾缺少WHERE product_id = $product_id 行。我已经更新了上面的代码。谢谢 @nalply 我在查询周围使用单引号,所以这无关紧要,该查询受到保护。在您发表评论之前,您是否也看到了我更新后的带有白名单的答案? 这不是易受 SQL 注入攻击吗? @arviman 它有mysql_real_escape_string 可以防止大多数注入尝试,但它不如使用准备好的语句。

以上是关于mysql中如何定义变量的主要内容,如果未能解决你的问题,请参考以下文章

mysql中使用@变量名:=值 生成的变量如何查看和删除?

尝试调用函数提交到 MySQL 时如何修复“未定义变量”

如何根据 HTML FORM 中定义的变量动态生成 MYSQL UPDATE 语句

MySQL中SELECT * FROM [变量] 如何实现?

如何在MYSQL用户定义函数中通过另一个字符串变量引用一个局部变量名?

如何给sqlserver 存储过程中的变量赋值?