Удаление ведущих нулей из varchar sql developer

Как удалить ведущие нули из числа, которое находится в форме varchar. Я попробовал следующее:

Вариант 1:

insert into example_table (columnName) 
    (SELECT
        SUBSTR(columnName2, InStr('%[^0 ]%', columnName2 + ' '), 10)
        from columnName2);

С этим я получаю ошибку

SQL Error: ORA-01722: invalid number
ORA-02063: preceding line from xxxx
01722. 00000 -  "invalid number"

Вариант 2:

insert into example_table (columnName) 
    (SELECT
        SUBSTR(columnName2, InStr('%[^0 ]%', columnName2 + ' '),  
        LEN(columnName2))
     from columnName2);

на этот раз я вам

Error at Command Line:23 Column:87
Error report:
SQL Error: ORA-00904: "LEN": invalid identifier

Вариант 3:

SUBSTRING
    (columnName2, PATINDEX('%[^0 ]%', columnName2 + ' '), 10));

подобно выше, я получаю

Error at Command Line:23 Column:41
Error report:
SQL Error: ORA-00904: "PATINDEX": invalid identifier
00904. 00000 -  "%s: invalid identifier"

редактировать

Я думаю, что маршрут обрезки может быть моим лучшим вариантом, однако... Я не знаю, как использовать его в моем случае.

INSERT INTO temp_table
(columnNeedTrim, column2, column3, column4, column5) 
    SELECT * FROM
        (SELECT(
      SELECT TRIM(leading '0' from columnNeedTrim) FROM table),
            table.column2, 
            table2.column3,
                table.column4
                table.column5
        FROM
        table 
        INNER JOIN 
        table2 ON
            table1.columnNeedTrim=table2.columnNeedTrim) 
    WHERE NOT EXISTS (SELECT * FROM temp_table);

теперь я получаю ошибку, потому что моя функция trim возвращает результат нескольких строк.

Error report:
SQL Error: ORA-01427: single-row subquery returns more than one row
01427. 00000 -  "single-row subquery returns more than one row"

Я не уверен, как работать с отделкой (или литой) в инструкции выше. Какая-нибудь помощь? Спасибо за любую помощь!

3 ответов


Oracle имеет встроенный TRIM функции для строк. Если у вас есть строка типа '00012345' и вы хотите сохранить его как строку, а не преобразовать его в фактическое NUMBER можно использовать LTRIM функции с дополнительным вторым setпараметр, указывающий, что вы выравниваете нули:

select ltrim('000012345', '0') from dual;

LTRIM
-----
12345

если у вас также могут быть ведущие пробелы, вы можете обрезать их за один раз:

select ltrim(' 00012345', '0 ') from dual;

LTRIM
-----
12345

вы также можете преобразовать в число и обратно, но это кажется как много работы, если у вас нет другого форматирования, которое вы хотите удалить:

select to_char(to_number('000012345')) from dual;

кстати, непосредственная причина, по которой вы получаете ORA-01722 с первой попытки, заключается в том, что вы используете числовое + оператор вместо оператора концентровки строк Oracle ||. Он выполняет неявное преобразование вашей строки в число, которого, похоже, вы пытаетесь избежать, и неявное преобразование одного пространства-что бы это ни было-вызывает ошибка. (Возможно, некоторые из ваших значений вообще не являются числами - еще один пример того, почему числа должны храниться в NUMBER поля; и если это так, то преобразование (или литье) в число и обратно все равно получит ORA-01722). Вы получите то же самое во второй попытке, если вы используете LENGTH вместо LEN. Ни один из них не будет работать в любом случае, как INSTR не распознает регулярные выражения. Вы могли бы использовать REGEXP_INSTR вместо этого, но вы бы лучше с @schurik по REGEXP_REPLACE версия, если вы хотите пойти по этому маршруту.


Я не уверен, что понимаю ваш вопрос edit. Похоже, ваша вставка может быть упрощена до:

INSERT INTO temp_table (columnNeedTrim, column2, column3, column4, column5)
SELECT LTRIM(table1.columnNeedTrim, '0 '),
    table1.column2,
    table1.column3,
    table1.column4,
    table1.column5
FROM table1
INNER JOIN table2 ON table2.columnNeedTrim = table1.columnNeedTrim
WHERE NOT EXISTS (
    SELECT * FROM temp_table
    WHERE columnNeedTrim = LTRIM(t42.columnNeedTrim, '0 '));

(Я не понимаю, почему вы делаете подзапрос в своей версии или почему вы получаете обрезанное значение из другое подзапрос.)

вы также можете использовать MERGE:

MERGE INTO temp_table tt
USING (
    SELECT LTRIM(t42.columnNeedTrim, '0 ') AS columnNeedTrim,
        t42.column2,
        t42.column3,
        t42.column4,
        t42.column5
    FROM t42 
    INNER JOIN t43 ON t43.columnNeedTrim=t42.columnNeedTrim
) sr
ON (sr.columnNeedTrim = tt.columnNeedTrim)
WHEN NOT MATCHED THEN
INSERT (tt.columnNeedTrim, tt.column2, tt.column3, tt.column4, tt.column5)
VALUES (sr.columnNeedTrim, sr.column2, sr.column3, sr.column4, sr.column5);

для SQL server, если вы знаете, что данные на самом деле число, вы можете просто привести его дважды. Кастинг на int удаляет ведущие нули, а затем возвращается к строке для вставки. Я предполагаю, что вы можете сделать что-то подобное в Oracle.

DECLARE @vc varchar(100) = '0000000000000000000001234'

SELECT CAST(CAST(@vc as int) as varchar(100))

возвращает:

1234

вам не нужно его заменять. Он будет обрабатываться Oracle.

SELECT  TO_NUMBER(num)
FROM
(
        SELECT '00000123' AS num FROM DUAL
);

-- Result:
-- 123