如何找出oracle数字的位数

时间:2011-08-04 12:29:43

标签: oracle plsql precision

我在oracle中有一个表,如下所示:

name              |     type    | nullable  
------------------------------------------
person_name       | varchar(20) | yes  
weight_coeficient | number      | yes
...

如何判断 weight_coeficient 的值有多少位数?例如:

3.0123456789有11个数字(precision = 11)和十进制后的10位数(scale = 10)

是否有任何sql命令/函数可以执行此操作,例如GetPrecision( select.. )返回11?

另请注意,表的定义未指定比例和精度。据我所知,所有数字都应用了最大精度。所以我不想找出定义的精度(= 48),而是表中特定值的精度。这可能只是使用oracle命令吗?

提前谢谢你,JP

3 个答案:

答案 0 :(得分:5)

怎么样......

SELECT LENGTH(TRANSLATE(TO_CHAR(3.0123456789),'1234567890.-','1234567890')) 
FROM dual

翻译只会删除非数字字符.-

答案 1 :(得分:0)

使用时略有改进:

length(to_char(:number)) - coalesce(length(translate(to_char(:number), 'x1234567890', 'x')), 0)

当to_char为指数或不同的分组字符或小数分隔符插入“E”时,它仍然有效。

答案 2 :(得分:0)

使用此脚本为您的数据生成适当的强制转换。我写这篇文章是为了帮助移动NUMBER数据,其中包含未指定的精度和数据。通过Kafka-Connect在Oracle中扩展到Postgres。 Kafka-Connect允许一个选择数据通过查询复制到另一个数据库,但由于我们没有在Oracle端设置我们的数字精度,Kafka-Connect将所有内容插入Postgres作为一个大小数。即,Oracle 1将被插入为1.000000000< 30 decimals>。

SET SERVEROUTPUT ON;
DECLARE
   Q1    VARCHAR2 (4000 CHAR);
   str   VARCHAR2 (300 CHAR);
BEGIN
   FOR rec
      IN (SELECT  column_name AS column_name
            FROM all_tab_cols
           WHERE     owner = 'YOUR_SCHEMA'
                 AND TABLE_NAME = 'YOUR_TABLE'
                 AND DATA_TYPE = 'NUMBER')
   LOOP
      q1 :=
         'SELECT    REPLACE(''cast( ''
             || :1
             || '' as  NUMBER(''
             || TO_CHAR (MAX (LENGTH_OF_DECIMAL) + MAX (length_of_integer))
             || '',''
             || TO_CHAR (MAX (length_of_decimal))
             || ''))'',''NUMBER(0,0)'',''NUMBER'') as result
        FROM (SELECT charnum,
                     CASE
                        WHEN INSTR (charnum, ''.'') > 0
                        THEN
                           SUBSTR (charnum, INSTR (charnum, ''.'') + 1)
                        ELSE
                           NULL
                     END
                        AS decimal_part,
                     CASE
                        WHEN INSTR (charnum, ''.'') > 0
                        THEN
                           REPLACE (
                              REPLACE (
                                 SUBSTR (charnum,
                                         1,
                                         INSTR (charnum, ''.'') - 1),
                                 ''-'',
                                 ''''),
                              ''+'',
                              '''')
                        ELSE
                           REPLACE (REPLACE (charnum, ''-'', ''''), ''+'', '''')
                     END
                        AS integer_part,
                     CASE
                        WHEN INSTR (charnum, ''.'') > 0
                        THEN
                           LENGTH (
                              SUBSTR (charnum, INSTR (charnum, ''.'') + 1))
                        ELSE
                           0
                     END
                        AS length_of_decimal,
                     CASE
                        WHEN INSTR (charnum, ''.'') > 0
                        THEN
                           NVL (
                              LENGTH (
                                 REPLACE (
                                    REPLACE (
                                       SUBSTR (charnum,
                                               1,
                                               INSTR (charnum, ''.'') - 1),
                                       ''-'',
                                       ''''),
                                    ''+'',
                                    '''')),
                              0)
                        ELSE
                           NVL (
                              LENGTH (
                                 REPLACE (REPLACE (charnum, ''-'', ''''),
                                          ''+'',
                                          '''')),
                              0)
                     END
                        AS length_of_integer
                FROM (SELECT cast(col_name2 AS VARCHAR2 (50))
                                AS charnum
                        FROM YOUR_TABLE)) T1';

      q1 := REPLACE (q1, 'col_name2', rec.column_name);

      EXECUTE IMMEDIATE REPLACE (q1, 'col_name2', rec.column_name)
         INTO str
         USING rec.column_name;

      DBMS_OUTPUT.PUT_LINE (str);
   END LOOP;
END;
/

测试用例:

create table precision_tester(test_val number); 

- 将YOUR_TABLE更改为PRECISION_TESTER

(运行脚本,验证输出,并在每次测试后从precision_tester中删除)

insert into precision_tester(test_val) values (null); 
insert into precision_tester(test_val) values (+1);
insert into precision_tester(test_val) values (-1);
insert into precision_tester(test_val) values (-1.00);
insert into precision_tester(test_val) values (+1.001);
insert into precision_tester(test_val) values (+12.001);

产生以下dbms输出:

cast( TEST_VAL as  NUMBER)
cast( TEST_VAL as  NUMBER(1,0))
cast( TEST_VAL as  NUMBER(1,0))
cast( TEST_VAL as  NUMBER(1,0))
cast( TEST_VAL as  NUMBER(4,3))
cast( TEST_VAL as  NUMBER(5,3))