我在数据库的几个表中有一堆记录,它们有一个“进程号”字段,这基本上是一个数字,但我必须将它存储为一个字符串,因为一些遗留数据有像“89a”这样的东西number 和一些要求将流程编号表示为数字/年份的编号系统。
当我尝试按编号对流程进行排序时,就会出现问题。我得到类似的东西:
- 1
- 10
- 11
- 12
另一个问题是当我需要添加一个新进程时。新进程的编号应该是现有的最大编号加一,为此我需要一种按编号对现有记录进行排序的方法。
有什么建议么?
我在数据库的几个表中有一堆记录,它们有一个“进程号”字段,这基本上是一个数字,但我必须将它存储为一个字符串,因为一些遗留数据有像“89a”这样的东西number 和一些要求将流程编号表示为数字/年份的编号系统。
当我尝试按编号对流程进行排序时,就会出现问题。我得到类似的东西:
另一个问题是当我需要添加一个新进程时。新进程的编号应该是现有的最大编号加一,为此我需要一种按编号对现有记录进行排序的方法。
有什么建议么?
您可以将数字存储为零填充值吗?也就是01、10、11、12?
我建议创建一个仅用于排序的新数字字段并从触发器更新它。
你能把数据分成两个字段吗?
将“进程号”存储为 int,将“进程子类型”存储为字符串。
那样:
那会做你需要的吗?
在我看来,您在这里有两个任务。
• 通过传统格式将字符串转换为数字/去除垃圾
• 对数字进行排序
如果您有一种实用的方法将字符串解析正则表达式引入您的流程(并且您的问题有足够的量值得付出努力),那么我会
• 创建一个参考表,例如CREATE TABLE tblLegacyFormatRegularExpressionMaster( LegacyFormatId int, LegacyFormatName varchar(50), RegularExpression varchar(max) )
• 然后,通过调用正则表达式的方式,例如 SQL Server 2005 及更高版本中的 CLR 集成(.NET 公共语言运行时集成,允许从 SQL Server 中调用已编译的 .NET 方法作为普通(Microsoft 扩展)T -SQL,那么你应该能够解决你的问题。
http://www.codeproject.com/KB/string/SqlRegEx.aspx
• 见
如果这对您手头的问题来说开销太大,我深表歉意。
鉴于您的流程编号似乎没有遵循任何固定模式(根据您的问题和评论),您是否可以构建/维护一个包含两个字段的流程编号表:
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
建议:
• 使您的列成为固定宽度的文本(即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”(或其他)拆分为单独的列的想法,但是我得到的印象是相关数据元素是一个标识符,因此不适合拆分它。
您需要在选择时投射您的字段。我将这种语法基于 MySQL - 但想法是一样的:
select * from table order by cast(field AS UNSIGNED);
当然,如果需要,可以签署 UNSIGNED。