【问题标题】:MySQL - how to front pad zip code with "0"?MySQL - 如何在“0”前面填充邮政编码?
【发布时间】:2010-07-08 04:56:31
【问题描述】:

在我的 MySQL InnoDB 数据库中,我有想要清理的脏邮政编码数据。

干净的邮政编码数据是当我拥有一个邮政编码的所有 5 位数字时(例如“90210”)。

但由于某种原因,我注意到在我的数据库中,对于以“0”开头的邮政编码,0 已被删除。

因此,邮政编码为“00544”的“Holtsville, New York”在我的数据库中存储为“544

邮政编码为“02026”的

Dedham, MA”在我的数据库中存储为“2026”。

我可以运行什么 SQL 到任何长度不是 5 位的邮政编码的前面填充“0”?意思是,如果邮政编码长度为 3 位,则前面填充“00”。如果邮政编码长度为 4 位,则前面填充“0”。

更新

我刚刚将邮政编码更改为数据类型 VARCHAR(5)

【问题讨论】:

  • 邮政编码的表格列似乎是数字类型,这导致了问题。在这种情况下,您必须更改数据类型以保留字符数据。
  • @Kangkan,你是对的。我的数据类型是数字。我刚刚将邮政编码转换为 varchar(5)。现在,如何去首页
  • 最好使用 CHAR 而不是 VARCHAR。当表变大时,它会大大加快查询速度(但前提是所有其他列的大小都是固定的)
  • 还要考虑其他国家的邮政编码并不总是 5 个字符。

标签: sql mysql database database-design


【解决方案1】:

将您的邮政编码存储为 CHAR(5) 而不是数字类型,或者在您从数据库加载时让您的应用程序用零填充它。使用sprintf() 使用 PHP 的一种方法:

echo sprintf("%05d", 205); // prints 00205
echo sprintf("%05d", 1492); // prints 01492

或者你可以让 MySQL 为你填充 LPAD():

SELECT LPAD(zip, 5, '0') as zipcode FROM table;

这是一种更新和填充所有行的方法:

ALTER TABLE `table` CHANGE `zip` `zip` CHAR(5); #changes type
UPDATE table SET `zip`=LPAD(`zip`, 5, '0'); #pads everything

【讨论】:

  • 我想实际清理数据库本身中的数据。你知道用 SQL 做这件事的等价物吗?
  • 我运行了以下代码使其工作“UPDATE tablename SET zip = LPAD(zip, 5, '0');”
  • 我认为这个“已接受”的答案不如 ZEROFILL 的答案。
  • 这个答案的一个缺陷。如果默认CHARACTER SET 是utf8,那CHAR(5) 将不必要地占用15 个字节!
【解决方案2】:

您需要确定邮政编码的长度(我认为应该是 5 个字符长)。然后你需要告诉 MySQL 将数字填零。

假设您的表名为mytable,相关字段为zipcode,请输入smallint。您需要发出以下查询:

ALTER TABLE mytable CHANGE `zipcode` `zipcode`
    MEDIUMINT( 5 ) UNSIGNED ZEROFILL NOT NULL;

这种方法的优点是它使您的数据保持不变,在数据插入/更新期间无需使用触发器,当您 SELECT 数据时无需使用函数,并且您始终可以删除多余的零或者如果您改变主意,请增加字段长度。

【讨论】:

  • 无符号 Zerofill 是可行的方法,尽管 smallint 的最大值为 65535。我建议使用 mediumint。卡利有 9xxxx 的拉链。
  • 如果您想支持其他国家/地区的邮政编码,您不需要整数。一些国家/地区在其邮政编码中使用字母。
【解决方案3】:

好的,您已将列从 Number 切换为 VARCHAR(5)。现在您需要将邮政编码字段更新为左填充。执行此操作的 SQL 将是:

UPDATE MyTable
SET ZipCode = LPAD( ZipCode, 5, '0' );

这会将 ZipCode 列中的所有值填充为 5 个字符,并在左侧添加“0”。

当然,既然您已经修复了所有旧数据,您需要确保您的任何新数据也都是零填充的。关于正确的做法,有几种思想流派:

  • 在应用程序的业务逻辑中处理它。优点:独立于数据库的解决方案,不涉及对数据库的更多了解。缺点:需要在所有应用程序中写入数据库的任何地方进行处理。

  • 使用存储过程处理它。优点:存储过程为所有客户端强制执行业务规则。缺点:存储过程比简单的 INSERT/UPDATE 语句更复杂,并且不能跨数据库移植。裸 INSERT/UPDATE 仍然可以插入非零填充数据。

  • 用触发器处理它。优点:适用于存储过程和裸 INSERT/UPDATE 语句。缺点:最不便携的解决方案。最慢的解决方案。触发器可能很难正确。

在这种情况下,我将在应用程序级别(如果有的话)而不是数据库级别处理它。毕竟,并非所有国家/地区都使用 5 位邮政编码(甚至美国也没有——我们的邮政编码实际上是 Zip+4+2:nnnnn-nnnn-nn),有些国家允许使用字母和数字。最好不要尝试强制数据格式并接受偶尔的数据错误,而不是阻止某人输入正确的值,即使它的格式与您期望的不太一样。

【讨论】:

    【解决方案4】:

    我知道这是在 OP 之后。您可以采用的一种方法是将表格存储为无符号 INT 但以零显示的邮政编码数据,如下所示。

    select LPAD(cast(zipcode_int as char), 5, '0') as zipcode from table;

    虽然这会将原始数据保留为 INT 并可以节省一些存储空间,但您将让服务器为您执行 INT 到 CHAR 的转换。这可以放入视图中,需要此数据的人可以被定向到那里而不是表本身。

    【讨论】:

      【解决方案5】:

      将邮政编码字段创建为填零的无符号整数字段仍然有意义。

      CREATE TABLE xxx ( zipcode INT(5) ZEROFILL UNSIGNED, ... )

      这样 mysql 会为您处理填充。

      【讨论】:

        【解决方案6】:
        CHAR(5)
        

        MEDIUMINT (5) UNSIGNED ZEROFILL
        

        第一个占每个邮政编码 5 个字节。

        第二个每个邮政编码只占用 3 个字节。 ZEROFILL 选项对于带有前导零的邮政编码是必需的。

        【讨论】:

          【解决方案7】:

          您应该在表结构中使用UNSIGNED ZEROFILL

          【讨论】:

            【解决方案8】:

            LPAD 与 VARCHAR2 一起使用,因为它不会为剩余字节放置空格。 LPAD 在 LHS 上将剩余/空字节更改为零 SO 数据类型应该是 VARCHAR2

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-01-07
              • 1970-01-01
              • 2015-07-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多