如何使用SQLite模拟LPAD / RPAD

时间:2011-07-04 21:52:05

标签: sql sqlite emulation padding

我很好奇如何以最一般的方式正式模拟SQLite的RPAD和LPAD函数。目标是能够做到

LPAD(column, character, repeat)
RPAD(column, character, repeat)

对于非常量表格列columncharacterrepeat。如果characterrepeat是已知常数,那么这将是一个好的,可行的解决方案:

但是如果上面的内容应该像这样执行怎么办:

SELECT LPAD(t.column, t.character, t.repeat) FROM t
SELECT LPAD(t.column, some_function(), some_other_function()) FROM t
SELECT LPAD(t.column, :some_bind_variable, :some_other_bind_variable) FROM t

如何通常模拟此LPAD函数?我迷失了各种可能性:

相关问题:

8 个答案:

答案 0 :(得分:17)

http://verysimple.com/2010/01/12/sqlite-lpad-rpad-function/

复制
-- the statement below is almost the same as
-- select lpad(mycolumn,'0',10) from mytable

select substr('0000000000' || mycolumn, -10, 10) from mytable

-- the statement below is almost the same as
-- select rpad(mycolumn,'0',10) from mytable

select substr(mycolumn || '0000000000', 1, 10) from mytable

答案 1 :(得分:4)

这对你来说更加肮脏:

X = padToLength
Y = padString
Z = expression

RPAD(对于LPAD,Z代替之后连接):

select 
    Z || 
    substr(
        replace(
            replace(
                substr(
                    quote(zeroblob(((X - length(Z) - 1 + length(Y)) / length(Y) + 1) / 2)), 
                    3
                ), 
                "'", 
                ""
            ), 
            "0", 
            Y
        ),
        1,
        (X - length(Z))
    )

示例:

sqlite> select "foo" || replace(replace(substr(quote(zeroblob((2 + 1) / 2)), 3, (2 - length("foo"))), "'", ""), "0", "W");
foo
sqlite> select "foo" || replace(replace(substr(quote(zeroblob((7 + 1) / 2)), 3, (7 - length("foo"))), "'", ""), "0", "W");
fooWWWW

Sqlite意味着非常轻量级,所以我不得不对你对由于缺乏功能而感到“惊讶”的评论表示不同意见。但是,我同意应该有一种更简单的方法来填充,只是因为存在trim函数。

答案 2 :(得分:4)

您也可以打印。

sqlite> SELECT PRINTF('%02d',5);
05
sqlite> SELECT PRINTF('%04d%02d',25,5);
002505
sqlite> 

答案 3 :(得分:2)

@ user610650解决方案的一个简单版本,使用hex()代替quote(),除了字符填充外,还可以使用字符串填充:

X = padToLength
Y = padString
Z = expression

select
    Z ||
    substr(
        replace(
            hex(zeroblob(X)),
            '00',
            Y
        ),
        1,
        X - length(Z)
    );

答案 4 :(得分:1)

JDBC /自定义函数方法(可能不适合您的确切情况,但可能可以进行调整)。使用来自{commics的SqliteJDBC Custom FunctionsrightPadleftPad函数的灵感.lang.Slang.StringUtils:

import java.sql.*;
import org.sqlite.Function;

public class Test 
{
  public static void main(String[] args) 
  {
    Connection conn = getConnection();

    conn.createStatement().execute("SELECT LPAD(t.column, t.character, t.repeat) FROM t");
    conn.createStatement().execute("SELECT RPAD(t.column, t.character, t.repeat) FROM t");

    conn.close();
  }

  public static Connection getConnection() 
  {
    Class.forName("org.sqlite.JDBC");
    Connection conn = DriverManager.getConnection("jdbc:sqlite:");

    /* Left Padding UDF  */
    Function.create(conn, "LPAD", new Function() 
      {
        protected void xFunc() throws SQLException 
        {
            String text = value_text(0);
            /* uses first character of supplied padding */
            char paddingCharacter = value_text(1).charAt(0);
            int repeat = value_int(2);

            int padLength = repeat - text.length();
            if(padLength <= 0)
            {
               result(text);
            }

            char[] padding = new char[padLength];
            Array.fill(padding, paddingCharacter);
            result(new String(padding).append(text));
        }
    });

    /* Right Padding UDF  */
    Function.create(conn, "RPAD", new Function() 
      {
        protected void xFunc() throws SQLException 
        {
            String text = value_text(0);
            /* uses first character of supplied padding */
            char paddingCharacter = value_text(1).charAt(0);
            int repeat = value_int(2);

            int padLength = repeat - text.length();
            if(padLength <= 0)
            {
               result(text);
            }

            char[] padding = new char[padLength];
            Array.fill(padding, paddingCharacter);
            result(text.append(new String(padding)));
        }
    });
  }
}

(未经测试,关闭袖口,不处理空值等,但应概述这个想法......)

答案 5 :(得分:1)

她是一个简单的解决方案,使用CASE填充0-9,前导零。

sqlite> select id,week,year from bulletin where id = 67;
67|2|2014

select id,CASE WHEN length(week) = 2 THEN week 
               ELSE '0'||week 
          END AS week,year from bulletin where id = 67;
67|02|2014

答案 6 :(得分:0)

也许是这样的:

  • LPAD(@orig_text, @padding_char, @padding_length)

    SELECT
      SUBSTR(
        REPLACE(
          CAST(ZEROBLOB(@padding_length) AS TEXT),
          CAST(ZEROBLOB(1) AS TEXT),
          @padding_char
        ) + @orig_text,
        -@padding_length,
        @paadding_length
      )
    
  • RPAD(@orig_text, @padding_char, @padding_length)

    SELECT
      SUBSTR(
        @orig_text + REPLACE(
          CAST(ZEROBLOB(@padding_length) AS TEXT),
          CAST(ZEROBLOB(1) AS TEXT),
          @padding_char
        ),
        1,
        @padding_length
      )
    

答案 7 :(得分:0)

我绝对没有使用SQLite的经验,实际上我与SQLite3 db交互的时间少于三天。因此,我不确定我的发现能否对您的要求有所帮助。

我正在玩一个有趣的项目,该项目拥有所有可能的11位电话号码(3位话务员前缀+ 8位用户号码)。我的目标是用最少的存储资源创建某种数据库,但必须覆盖数据库上的所有可能数量。因此,我为8位订户创建了一个表,而另一个表包含3位公司前缀。最终编号将出现在连接两个表数据的视图上。让我专注于LOAD问题。由于订户表列为INT,因此它是0到99999999的单个记录。如果用户数少于10000000,则简单加入失败;值在10000000以下的所有订阅者订阅ID号都显示XXXprefix + 11,其中期望XXX000000 + 11。

在SQLite上使用LPAD / RPAD失败后,我找到了“ SUBSTR”!

看看下面的查询:

CREATE TABLE subs_num (
subscriber_num integer PRIMARY KEY
);

INSERT INTO subs_num values ('1');
INSERT INTO subs_num values ('10');
INSERT INTO subs_num values ('100');
INSERT INTO subs_num values ('1000');

SELECT subscriber_num from subs_num;

SELECT SUBSTR('00000000' || subscriber_num, -8, 8) AS SUBSCRIB_ID FROM subs_num;

现在,我认为您可以将SUBSTR用于您的LPAD / RPAD。

干杯!