赞
踩
新近安装了一批DM8的生产库和测试库,现有生产库多为Oracle数据库,运维力量集中在Oracle,团队也开始DM的认证与学习。DM数据库与Oracle数据库的兼容性,使得学习达梦显得比较容易。但DM特有的内容,还是要看官方文档。
比如前段时间,新安装的数据库在查询系统时间时结果不正确。( select sysdate from dual;)
最终确认原因:按照Linux和oracle的参数设置习惯,东八区的参数设置为“+ 08:00”,
DM数据库安装后,设置了如下时区,查询系统时间错误:
错误设置:
[root@dem ~]# vi /etc/dm_svc.conf
TIME_ZONE=(+08:00)
LANGUAGE=(en)
正确的设置:
[root@dem ~]# cat /etc/dm_svc.conf
TIME_ZONE=(480)
LANGUAGE=(en)
在修改参数并重启数据库后,系统查询时间正常。
公 式 : s u m ( n ) = ∑ 1 n 1 n 公式 :sum(n)=\displaystyle\sum_1^n\frac 1 n 公式:sum(n)=1∑nn1
我 们 只 计 算 前 10 项 : s u m ( 10 ) = 1 1 + 1 2 + 1 3 + ⋯ + 1 9 + 1 10 我们只计算前10项:sum(10)=\displaystyle\frac 1 1+\frac 1 2+\frac 1 3+\dots+\frac 1 9+\frac 1 {10} 我们只计算前10项:sum(10)=11+21+31+⋯+91+101
在Oracle中使用一个简单的FOR循环,即可实现,为了直观,显示了中间的每个分数计算结果。
完整测试如下:
C:\Users\cdb>sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on 星期二 12月 6 17:02:07 2022 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. 连接到: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1/n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1/n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=.5 Values of 1/3=.3333333333333333333333333333333333333333 Values of 1/4=.25 Values of 1/5=.2 Values of 1/6=.1666666666666666666666666666666666666667 Values of 1/7=.1428571428571428571428571428571428571429 Values of 1/8=.125 Values of 1/9=.1111111111111111111111111111111111111111 Values of 1/10=.1 Values of 1/1+1/2+1/3+...+1/10=2.92896825396825396825396825396825396825 PL/SQL 过程已成功完成。 SQL>
使用和Oracle中一样的FOR循环结构,语法正确,显示结果错误:
完整测试如下:
[dmdba@dem ~]$ disql sysdba/Oracle_123@localhost:1801 Server[localhost:1801]:mode is normal, state is open login used time : 2.523(ms) disql V8 SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1/n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1/n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=0 Values of 1/3=0 Values of 1/4=0 Values of 1/5=0 Values of 1/6=0 Values of 1/7=0 Values of 1/8=0 Values of 1/9=0 Values of 1/10=0 Values of 1/1+1/2+1/3+...+1/10=1E0 DMSQL executed successfully used time: 1.346(ms). Execute id is 601. SQL> SQL>
考虑到DM的兼容性参数设置影响,修改了数据库参数COMPATIBLE_MODE=2 。
修改配置文件dm.ini后并重新启动数据库。
[dmdba@dem ~]$ vi /dm/data/DEM/dm.ini
#DaMeng Database Server Configuration file
COMPATIBLE_MODE = 2 #Server compatible mode, 0:none, 1:SQL92, 2:Oracle, 3:MS SQL Server, 4:MySQL, 5:DM6, 6:Teradata
重新执行FOR循环语句,依然报错:
[dmdba@dem ~]$ disql sysdba/Oracle_123@localhost:1801 Server[localhost:1801]:mode is normal, state is open login used time : 2.344(ms) disql V8 SQL> select PARA_NAME,PARA_VALUE,PARA_TYPE from v$dm_ini where para_name like 'COMPA%'; LINEID PARA_NAME PARA_VALUE PARA_TYPE ---------- --------------- ---------- --------- 1 COMPATIBLE_MODE 2 IN FILE DMSQL executed successfully used time: 0.453(ms). Execute id is 1601. SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1/n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1/n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=0 Values of 1/3=0 Values of 1/4=0 Values of 1/5=0 Values of 1/6=0 Values of 1/7=0 Values of 1/8=0 Values of 1/9=0 Values of 1/10=0 Values of 1/1+1/2+1/3+...+1/10=1E0 used time: 8.128(ms). Execute id is 1602. SQL>
看到分数运算测试结果,数据库运维人员应该立刻敏感的意识到两个问题,一是运算结果错误本身,二是我们的一大堆监控脚本等怎么办?
看到 1/10没有感觉?
SQL> select 1/10 from dual;
LINEID 1/10
---------- -----------
1 0
used time: 7.240(ms). Execute id is 500.
那么这个呢?
SQL> select 5/1440 from dual;
LINEID 5/1440
---------- -----------
1 0
used time: 0.466(ms). Execute id is 501.
再看看这个,我要的5分钟前怎么办?
SQL> select sysdate,sysdate-5/1440 from dual;
LINEID SYSDATE SYSDATE-5/1440
---------- ------------------- -------------------
1 2022-12-12 12:16:28 2022-12-12 12:16:28
used time: 5.318(ms). Execute id is 502.
睁大眼睛仔细看差异,下面的程序比之前的多了两个点(“."),分别在2行中。
SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1./n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1./n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=0.5 Values of 1/3=0.3333333333333333333333333333333333333 Values of 1/4=0.25 Values of 1/5=0.2 Values of 1/6=0.1666666666666666666666666666666666667 Values of 1/7=0.1428571428571428571428571428571428571 Values of 1/8=0.125 Values of 1/9=0.1111111111111111111111111111111111111 Values of 1/10=0.1 Values of 1/1+1/2+1/3+...+1/10=2.928968253968254E0 DMSQL executed successfully used time: 0.847(ms). Execute id is 1609.
其实因该是这样的:
SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1.0/n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1.0/n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=0.5 Values of 1/3=0.3333333333333333333333333333333333333 Values of 1/4=0.25 Values of 1/5=0.2 Values of 1/6=0.1666666666666666666666666666666666667 Values of 1/7=0.1428571428571428571428571428571428571 Values of 1/8=0.125 Values of 1/9=0.1111111111111111111111111111111111111 Values of 1/10=0.1 Values of 1/1+1/2+1/3+...+1/10=2.928968253968254E0 DMSQL executed successfully used time: 0.902(ms). Execute id is 1607.
终极同框对比:
SQL> select 1/10 from dual; LINEID 1/10 ---------- ----------- 1 0 used time: 0.132(ms). Execute id is 509. SQL> select 1.0/10 from dual; LINEID 1./10 ---------- ----- 1 0.1 used time: 0.157(ms). Execute id is 510. SQL> select 1./10 from dual; LINEID 1./10 ---------- ----- 1 0.1 used time: 0.288(ms). Execute id is 511. SQL> select 5/1440 from dual; LINEID 5/1440 ---------- ----------- 1 0 used time: 0.182(ms). Execute id is 512. SQL> select 5.0/1440 from dual; LINEID 5./1440 ---------- ----------------------------------------- 1 0.003472222222222222222222222222222222222 used time: 0.226(ms). Execute id is 513. SQL> select 5./1440 from dual; LINEID 5./1440 ---------- ----------------------------------------- 1 0.003472222222222222222222222222222222222 used time: 0.191(ms). Execute id is 514. SQL> select sysdate,sysdate-5/1440 from dual; LINEID SYSDATE SYSDATE-5/1440 ---------- ------------------- ------------------- 1 2022-12-12 12:35:43 2022-12-12 12:35:43 used time: 0.201(ms). Execute id is 515. SQL> SQL> select sysdate,sysdate-5.0/1440 from dual; LINEID SYSDATE SYSDATE-5./1440 ---------- ------------------- ------------------- 1 2022-12-12 12:35:52 2022-12-12 12:30:52 used time: 0.171(ms). Execute id is 516. SQL> SQL> select sysdate,sysdate-5./1440 from dual; LINEID SYSDATE SYSDATE-5./1440 ---------- ------------------- ------------------- 1 2022-12-12 12:35:57 2022-12-12 12:30:57 used time: 0.162(ms). Execute id is 517.
前一段时间重拾C语言,亦遇到类似问题,本次特地测试了C++和C语言的文章开头分数累加公式:
C++源程序:
#include <iostream>
using namespace std;
int main()
{
int n;
float sum = 0;
for(int n=1;n<=10;n++)
{
cout << "1/" <<n<< "="<< 1/n<<endl;
sum = sum+ 1/n;
}
cout << "1/1+1/2+1/3+...+1/8+1/9+1/10=" << sum<<endl;
return 0;
}
修改代码加入1.0:
修成程序加入1.:
C语言测试:
源程序:
#include <stdio.h>
int main()
{
int n;
float sum = 0;
for(int n=1;n<=10;n++)
{
printf("1/%d=%d\n" ,n,1/n) ;
sum += 1/n;
}
printf("1/1+1/2+1/3+...+1/8+1/9+1/10=%f" ,sum);
return 0;
}
结果错误:
增加1.0的结果:
加入1.结果:
作为学习过程,保留下面信息:
(在Oracle数据库中,隐式转换帮我们处理了类似1/9=0的问题,默认显示为小数结果。而在DM数据库中,需要我们自己处理这个问题,除法输入中必须有一个是浮点数(1.0/9或者1/9.0),运算结果显示为小数。就像我使用C或者C++编写程序代码的测试一样。 建议DM数据库最好还是默认实现这个隐式转换,为Oracle数据库向DM数据库的迁移提供便利。 )
在咨询DM工程师后,给出了在设置DM兼容Oracle参数后,再设置CALC_AS_DECIMAL =1可以解决该问题。
COMPATIBLE_MODE = 2 #Server compatible mode, 0:none, 1:SQL92, 2:Oracle, 3:MS SQL Server, 4:MySQL, 5:DM6, 6:Teradata
CALC_AS_DECIMAL = 1 #Whether integer CALC as decimal, 0: no, 1:only DIV, 2:all only has charactor, 3:all for digit
最终测试:
[dmdba@dem ~]$ disql sysdba/Oracle_123@localhost:1801 Server[localhost:1801]:mode is normal, state is open login used time : 4.269(ms) disql V8 SQL> select PARA_NAME,PARA_VALUE,PARA_TYPE from v$dm_ini where para_name like 'CALC_AS_DECIMAL%'; LINEID PARA_NAME PARA_VALUE PARA_TYPE ---------- --------------- ---------- --------- 1 CALC_AS_DECIMAL 1 IN FILE used time: 9.418(ms). Execute id is 600. SQL> select PARA_NAME,PARA_VALUE,PARA_TYPE from v$dm_ini where para_name like 'COMPA%'; LINEID PARA_NAME PARA_VALUE PARA_TYPE ---------- --------------- ---------- --------- 1 COMPATIBLE_MODE 2 IN FILE used time: 10.104(ms). Execute id is 601. SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 n int:=1; 3 v_n float:=0; 4 v_sum float:=0; 5 BEGIN 6 for n in 1..10 LOOP 7 SELECT 1/n into v_n FROM dual; 8 v_sum:=v_sum+v_n; 9 dbms_output.put_line('Values of 1/'||n||'='||1/n); 10 END LOOP; 11 dbms_output.put_line('Values of 1/1+1/2+1/3+...+1/10='||v_sum); 12 END; 13 / Values of 1/1=1 Values of 1/2=0.5 Values of 1/3=0.3333333333333333333333333333333333333 Values of 1/4=0.25 Values of 1/5=0.2 Values of 1/6=0.1666666666666666666666666666666666667 Values of 1/7=0.1428571428571428571428571428571428571 Values of 1/8=0.125 Values of 1/9=0.1111111111111111111111111111111111111 Values of 1/10=0.1 Values of 1/1+1/2+1/3+...+1/10=2.928968253968254E0 DMSQL executed successfully used time: 0.541(ms). Execute id is 603. SQL>
结果与Oracle的返回一致,可以直接测试我的那些监控脚本了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。