数据库迁移常见语法问题
DM数据库常见语法差异
一.Sql文语法
1.杀进程语法
select * from v$lock;
select * from sysobjects;--(查询对象信息)
select * from v$sessions;--(查询会话信息)
--上述3条语句组合一下就能查出哪张表上的某种锁是由哪个会话里的操作加上的
--查哪张表上的某种锁是由哪个会话里的操作加上的
select a.*,b.NAME,c.SESS_ID from v$lock a
left join sysobjects b on b.ID=a.TABLE_ID
left join v$sessions c on a.TRX_ID=c.TRX_ID;
--找到表名对应的SESS_ID,使用系统函数 blocked=1表示锁了
sp_close_session(sess_id);
--干掉对应的会话
2.删除失败显示进程占用
--删除的过程中查询
--查找wait_for_id
select * from v$trxwait ;
--2084552 根据wait_for_id找到sess_id
SELECT sess_id, sql_text, state, trx_id
FROM v$sessions
WHERE trx_id =2084552;
--173471336 杀掉sess_id
sp_close_session(173471336);
3.RECURSIVE递归查询关键字
在达梦中递归查询会报错,需要指明CTE列名称
--会报错
WITH RECURSIVE cte AS (
-- 基础情况:选择顶级商品(没有父代码的商品)
SELECT rg.*
FROM rm_goods rg
LEFT JOIN rm_goods c ON rg.parentcode_ = c.code_
UNION ALL
-- 递归部分:选择每个商品的直接子商品
SELECT rg.*
FROM rm_goods rg
INNER JOIN cte e1 ON rg.parentcode_ = e1.code_ -- 关联到父商品
)
SELECT * FROM cte ;
--正确书写方法
WITH RECURSIVE cte(code_,name_,parentcode_,memo_,isroot_,rootcode_) AS (
-- 基础情况:选择顶级商品(没有父代码的商品)
SELECT rg.*
FROM rm_goods rg
LEFT JOIN rm_goods c ON rg.parentcode_ = c.code_
UNION ALL
-- 递归部分:选择每个商品的直接子商品
SELECT rg.*
FROM rm_goods rg
INNER JOIN cte e1 ON rg.parentcode_ = e1.code_ -- 关联到父商品
)
SELECT * FROM cte ;
4.使用CTE递归查询联合查询需要使用union all,使用union会报错
--使用CTE递归查询联合查询需要使用union all,使用union会报错
--报错
WITH RECURSIVE cte(CODE_,
NAME_,
STATE_,
ISROOT_,
ISLEAF_,
PARENTCODE_,
ROOTCODE_) AS
(SELECT rg.CODE_, rg.NAME_, rg.STATE_, rg.ISROOT_, rg.ISLEAF_,
rg.PARENTCODE_, rg.ROOTCODE_
FROM rm_label rg
where rg.isroot_ = '1'
UNION
SELECT t.CODE_, t.NAME_, t.STATE_, t.ISROOT_, t.ISLEAF_, t.PARENTCODE_,
t.ROOTCODE_
from cte t)
SELECT * FROM cte;
--正常
WITH RECURSIVE cte(CODE_,
NAME_,
STATE_,
ISROOT_,
ISLEAF_,
PARENTCODE_,
ROOTCODE_) AS
(SELECT rg.CODE_, rg.NAME_, rg.STATE_, rg.ISROOT_, rg.ISLEAF_,
rg.PARENTCODE_, rg.ROOTCODE_
FROM rm_label rg
where rg.isroot_ = '1'
UNION all
SELECT t.CODE_, t.NAME_, t.STATE_, t.ISROOT_, t.ISLEAF_, t.PARENTCODE_,
t.ROOTCODE_
from cte t)
SELECT * FROM cte;
二.存储过程
1.创建存储过程参数不要指定具体长度
--报错写法
CREATE or replace PROCEDURE pr_test(
i_param1 in int(10),
i_param1 in varchar(10),
i_param1 in varchar(10),
O_RETURN_CURSOR out CURSOR
) as
begin
open O_RETURN_CURSOR for
select 1 from dual;
end
--正确写法
CREATE or replace PROCEDURE pr_test(
i_param1 in int,
i_param1 in varchar,
i_param1 in varchar,
O_RETURN_CURSOR out CURSOR
) as
begin
open O_RETURN_CURSOR for
select 1 from dual;
end
2.达梦存储过程调用时无法直接显示返回游标
CREATE TABLE "RM"."rm_test"
(
"code_" VARCHAR2(10),
"name_" VARCHAR2(10)
);
CREATE or replace PROCEDURE pr_test(
i_param1 in int(10),
i_param1 in varchar(10),
i_param1 in varchar(10),
O_RETURN_CURSOR out CURSOR
) as
begin
--结果无法直接显示
open O_RETURN_CURSOR for
select * from rm_test;
end
正确做法创建表
create table rm_test01 as select * from rm_test;
CREATE or replace PROCEDURE pr_test(
i_param1 in int(10),
i_param1 in varchar(10),
i_param1 in varchar(10),
O_RETURN_CURSOR out CURSOR
) as
begin
insert into rm_test01 as select * from rm_test;
open O_RETURN_CURSOR for
select * from rm_test;
end
存储过程调用结束后查询rm_test01;
3.存储过程中达梦多行更新报错,没有语法问题,修改参数MULTI_UPD_OPT_FLAG
--报错
create or replace procedure pr_test() as
begin
update cmn_code t
set (t.code_, t.name_) =
(select k.code_, k.name_ from cmn_code_bk k where k.id_ = t.id_)
where exists (select 1 from cmn_code_bk k where k.id_ = t.id_);
end;
--可单独执行成功
update cmn_code t
set (t.code_, t.name_) =
(select k.code_, k.name_ from cmn_code_bk k where k.id_ = t.id_)
where exists (select 1 from cmn_code_bk k where k.id_ = t.id_);
--修改参数
ALTER SYSTEM SET MULTI_UPD_OPT_FLAG = 1;
/*MULTI_UPD_OPT_FLAG 是达梦数据库中的一个参数,它的作用是控制是否使用优化的多列更新。
当该参数设置为1时,数据库会利用多列存储过程(SPL)功能来实现多列更新,而不是按照传统的语句改写方式。
这可以提高多列更新操作的效率。其默认值为0,表示不使用优化的多列更新,而是使用传统的语句改写方式实现 。*/
数据库迁移常见校验语句
1.查询mysql表名及数据行数
SELECT
TABLE_NAME AS tablename,
TABLE_ROWS AS tablerows
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'rm' AND
TABLE_TYPE = 'BASE TABLE';
2.查询达梦表名及数据行数
SELECT TABLE_NAME, NUM_ROWS
FROM DBA_TAB_STATISTICS t
WHERE t.TABLE_OWNER = 'rm';
3.清除表数据(迁移用)
DECLARE
v_table_name VARCHAR2(50);
BEGIN
FOR t IN (SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = 'rm') LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || t.TABLE_NAME;
END LOOP;
COMMIT;
END;