【问题标题】:Ordering numbers that are stored as strings in the database以字符串形式存储在数据库中的订货号
【发布时间】:2008-10-16 22:23:00
【问题描述】:

我在数据库的几个表中有一堆记录,这些记录有一个“进程号”字段,基本上是一个数字,但我必须将它存储为一个字符串,因为一些遗留数据包含“89a”之类的内容" 作为一个数字和一些编号系统,要求将流程编号表示为数字/年份。

当我尝试按编号对进程进行排序时,就会出现问题。我得到类似的东西:

  • 1
  • 10
  • 11
  • 12

另一个问题是当我需要添加一个新进程时。新进程的编号应该是现有的最大编号加一,为此我需要一种按编号对现有记录进行排序的方法。

有什么建议吗?

【问题讨论】:

    标签: database language-agnostic sql-order-by


    【解决方案1】:

    Maybe this will help.

    基本上:

    SELECT process_order FROM your_table ORDER BY process_order + 0 ASC
    

    【讨论】:

      【解决方案2】:

      您可以将数字存储为零填充值吗?也就是01、10、11、12?

      【讨论】:

        【解决方案3】:

        我建议创建一个仅用于排序的新数字字段并从触发器更新它。

        【讨论】:

          【解决方案4】:

          你能把数据分成两个字段吗?

          将“进程号”存储为 int,将“进程子类型”存储为字符串。

          这样:

          • 您可以轻松获得 MAX processNumber - 并在需要生成 新号码
          • 您可以通过 processNumber ASC 订购, processSubtype ASC - 获取 正确的顺序,即使多个记录具有相同的基数并附加了不同的年份/字母
          • 当您需要“完整”号码时 可以只连接两个字段

          这能满足你的需要吗?

          【讨论】:

            【解决方案5】:

            鉴于您的进程号似乎没有遵循任何固定模式(根据您的问题和 cmets),您能否构建/维护一个包含两个字段的进程号表:

            create table process_ordering ( processNumber varchar(N), processOrder int )
            

            然后从您的表中选择所有进程号并插入到进程号表中。根据(不同的)进程编号格式设置您想要的排序。加入此表,按 processOrder 排序并从另一个表中选择所有字段。在 processNumber 上索引此表以加快连接速度。

            select my_processes.*
            from my_processes
              inner join process_ordering on my_process.processNumber = process_ordering.processNumber
            order by process_ordering.processOrder
            

            【讨论】:

              【解决方案6】:

              在我看来你有两个任务。

              • 通过旧格式将字符串转换为数字/去除垃圾
              • 对数字进行排序

              如果您有一种实用的方法将字符串解析正则表达式引入您的流程(并且您的问题有足够的量值得付出努力),那么我会

              • 创建一个参考表,例如
              
              CREATE TABLE tblLegacyFormatRegularExpressionMaster(
                  LegacyFormatId int,
                  LegacyFormatName varchar(50),
                  RegularExpression varchar(max)
              )
              

              • 然后,通过调用正则表达式的方式,例如 SQL Server 2005 及更高版本中的 CLR 集成(.NET 公共语言运行时集成允许从 SQL Server 中调用已编译的 .NET 方法普通(微软扩展)T-SQL,那么你应该能够解决你的问题。

                    • 见

              http://www.codeproject.com/KB/string/SqlRegEx.aspx


              如果这对您手头的问题来说开销太大,我深表歉意。

              【讨论】:

                【解决方案7】:

                建议:

                • 使您的列成为固定宽度的文本(即CHAR 而不是VARCHAR)。

                • 用足够的前导零填充现有值以填充每列和一个尾随空格,其中值不以“a”(或其他)结尾。 • 添加CHECK 约束(或等效项)以确保新值符合模式,例如像

                CHECK (process_number LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][ab ]')
                

                • 在您的插入/更新存储过程(或等效过程)中,填充任何传入值以适应模式。

                • 在向人类显示值时,酌情删除前导/尾随零/空格。

                这种方法的另一个优点是传入的值“1”、“01”、“001”等都将被视为相同的值,并且可以通过 DBMS 中的简单唯一约束来覆盖。

                顺便说一句,我喜欢将尾随的“a”(或其他任何内容)拆分为单独列的想法,但我认为相关数据元素是一个标识符,因此不适合拆分它。

                【讨论】:

                  【解决方案8】:

                  您需要在选择时投射您的字段。我将这种语法基于 MySQL - 但想法是一样的:

                  select * from table order by cast(field AS UNSIGNED);
                  

                  当然,如果需要,也可以对 UNSIGNED 进行签名。

                  【讨论】:

                  • 当我有像“62a”和“12/98”这样的“数字”时会中断,就像我在问题中解释的那样。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-10-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多