---
title: MySQL的存储过程中参数名和列名同名时使用的究竟是哪一个？-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于MySQL的存储过程中参数名和列名同名时使用的究竟是哪一个？相关的常见问题和使用技巧，帮助您快速解决MySQL的存储过程中参数名和列名同名时使用的究竟是哪一个？的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# MySQL的存储过程中参数名和列名同名时使用的究竟是哪一个？

更新时间：2026-05-29 08:46

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x、V4.0.x、V4.1.x、V4.2.x 内容类型：FAQ  

在一些编码风格较差的 PL/SQL 代码中，往往会遇到传入的参数/用户自定义变量和表的列名同名的情况，这种情形下，PL/SQL 解析器究竟引用的是哪一个呢？ 本文主要介绍这种场景下PL/SQL解析器实际的解析情况。

## 详细说明

在 MySQL 中，如果在存储过程或函数中参数和列同名，参数将优先。如果需要引用表中的列，需要使用表的别名或者是 `TABLE_NAME.COLUMN_NAME` 的形式来明确指出是列而不是参数。 例如，假设有一个名为 `users` 的表，其中包含一个名为 `name` 的列，你有一个存储过程 `GetUser`，它有一个名为 `name` 的参数：

```shell
CREATE PROCEDURE GetUser(IN name VARCHAR(255))
BEGIN
    SELECT name FROM users WHERE name = name;
END;

```

在这个存储过程中，`SELECT` 语句中引用到的三个 `name` 会引用参数 `name`，而不是 `users` 表的列。为了引用表的列，你需要修改查询如下：

```shell
CREATE PROCEDURE GetUser(IN name VARCHAR(255))
BEGIN
    SELECT users.name FROM users WHERE users.name = name;
END;

```

或者使用表的别名：

```shell
CREATE PROCEDURE GetUser(IN name VARCHAR(255))
BEGIN
    SELECT u.name FROM users AS u WHERE u.name = name;
END;

```

在上述这两个示例中，`users.name` 或 `u.name` 都指向 `users` 表的 `name` 列，而不是存储过程的参数。

**OceanBase 数据库 MySQL 租户中针对这种歧义时的行为表现和原生 MySQL一样**。示例如下：

1. 通过 MySQL 客户端连接 OceanBase 数据库的 MySQL 模式租户。

   ```shell
   [root@xxx ~]# mysql -h127.1 -uroot@mysql -P2881 -pxxx -A -c test

   ```

   登录成功后，返回如下结果：

   ```shell
   Welcome to the MariaDB monitor.  Commands end with ; or \g.
   Your MySQL connection id is 3221658603
   Server version: 5.7.25 OceanBase 4.2.1.8 (r108000052024072217-77f9516419866bc291fc79b950b0865f2f4194e0) (Built Jul 22 2024 17:42:10)

   Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

   Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

   ```
 2. 创建表 users。

   ```shell
   MySQL [test]> create table users (name varchar(100));
   Query OK, 0 rows affected (0.094 sec)

   ```
 3. 向表 users 插入数据。

   ```shell
   MySQL [test]> insert into users values ('Bob'),('Jack'),('Tom');
   Query OK, 3 rows affected (0.022 sec)
   Records: 3  Duplicates: 0  Warnings: 0

   ```
 4. 提交数据。

   ```shell
   MySQL [test]> commit;
   Query OK, 0 rows affected (0.000 sec)

   ```
 5. 查询表 users 内容。

   ```shell
   MySQL [test]> select * from users;

   ```

   输出结果如下：

   ```shell
   +------+
   | name |
   +------+
   | Bob  |
   | Jack |
   | Tom  |
   +------+
   3 rows in set (0.003 sec)

   ```
 6. 使用 delimiter 命令修改结束符为 `;;`。

   ```shell
   MySQL [test]> delimiter ;;

   ```
 7. 创建存储过程 GetUser。

   ```shell
   MySQL [test]> CREATE PROCEDURE GetUser(IN name VARCHAR(255))
   BEGIN
    SELECT name FROM users WHERE name = name;
   END;
   ;;
   Query OK, 0 rows affected (0.048 sec)

   ```

   #### 说明

   这边如果将 `BEGIN ... END` 之间的 `name` 都加上反引号 `` `name` ``，效果是一样的。
 8. 使用 delimiter 命令修改结束符为默认符号分号（;）。

   ```shell
   MySQL [test]> delimiter ;

   ```
 9. 调用存储过程 GetUser。

   ```shell
   MySQL [test]> call GetUser('Bob');

   ```

   输出结果如下：

   ```shell
   +------+
   | name |
   +------+
   | Bob  |
   | Bob  |
   | Bob  |
   +------+
   3 rows in set (0.001 sec)

   Query OK, 0 rows affected (0.001 sec)

   ```

   ```shell
   MySQL [test]> call GetUser('xxx');

   ```

   输出结果如下：

   ```shell
   +------+
   | name |
   +------+
   | xxx  |
   | xxx  |
   | xxx  |
   +------+
   3 rows in set (0.001 sec)

   ```
 10. 删除数据库中已经存在的存储过程 GetUser 并防止因删除不存在的存储过程而引发的错误。

    ```shell
    MySQL [test]> drop procedure if exists GetUser;
    Query OK, 0 rows affected (0.047 sec)

    ```
 11. 使用 delimiter 命令修改结束符为 `;;`。

    ```
 12. 创建存储过程 GetUser。

    ```shell
    MySQL [test]> CREATE PROCEDURE GetUser(IN name VARCHAR(255))
    BEGIN
    SELECT u.name FROM users AS u WHERE u.name = name;
    END;
    ;;
    Query OK, 0 rows affected (0.046 sec)

    ```
 13. 使用 delimiter 命令修改结束符为默认符号分号（;）。

    ```
 14. 调用存储过程 GetUser。

    ```

    输出结果如下：

    ```shell
    +------+
    | name |
    +------+
    | Bob  |
    +------+
    1 row in set (0.007 sec)

    Query OK, 0 rows affected (0.007 sec)

    ```

    ```shell
    MySQL [test]> call GetUser('xxx');
    Empty set (0.001 sec)

    ```

更权威的解释可以参考 MySQL 官方文档的内容：[15.6.4.2 Local Variable Scope and Resolution](https://dev.mysql.com/doc/refman/8.4/en/local-variable-scope.html)，涉及的内容如下。

```shell
A local variable should not have the same name as a table column. If an SQL statement, such as a SELECT ... INTO statement, contains a reference to a column and a declared local variable with the same name, MySQL currently interprets the reference as the name of a variable. Consider the following procedure definition:
CREATE PROCEDURE sp1 (x VARCHAR(5))
BEGIN
  DECLARE xname VARCHAR(5) DEFAULT 'bob';
  DECLARE newname VARCHAR(5);
  DECLARE xid INT;

  SELECT xname, id INTO newname, xid
    FROM table1 WHERE xname = xname;
  SELECT newname;
END;
MySQL interprets xname in the SELECT statement as a reference to the xname variable rather than the xname column. Consequently, when the procedure sp1()is called, the newname variable returns the value 'bob' regardless of the value of the table1.xname column.

```

#### 说明

类似上面这种传入的参数/用户自定义变量和表的列名同名的情形是一种非常不好的 `PL/SQL` 编码风格，优秀的 `PL/SQL` 代码应该杜绝存储过程或函数的传入参数/自定义变量与列名同名的情况。比如将上面的传入参数名称改为 `p_name` 就可以了。

## 适用版本

OceanBase 数据库 V2.x、V3.x、V4.x 版本。

上一篇

[ARM 平台 PL 编译阶段 allocate_mapped_memory 分配内存卡住](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000001277161)

下一篇

[PL 内部含有大量静态 SQL 可能导致 core dump](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002045132) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
