我在oracle中有一个表MyTable:
MXP_ID MX_ID TB_SRC DESC COL_LOC
1 MX3 MB_SHEET_ROW TEST APS
1 MX1 MB_SHEET_ROW DEV APT
1 MX120 MB_SHEET_ROW PROD APU
1 MX5 MB_SHEET_ROW SET APV
1 MX6 MB_SHEET_ROW CHECK APW
1 MX54 MB_SHEET_ROW WHILE APX
1 MX14 MB_SHEET_ROW DO APY
1 MX2 MB_SHEET_ROW FOR APZ
这是一个excel表,其中字段colloc指定不同的列: 那就是excel表示:
APS APT APU APV APW APX APY APZ
MX3 MX1 MX120 MX5 MX6 MX54 MX14 MX2
如果我在APT列之后在上面的Excel中插入一个新列,那么在生成的excel MX120中将转移到列APV,依此类推..
APS APT APU APV APW APX APY APZ AQA
MX3 MX1 MX_NEW MX120 MX5 MX6 MX54 MX14 MX2
因此,oracle中的相应表将被修改为: MyTable的:
MXP_ID MX_ID TB_SRC DESC COL_LOC
1 MX3 MB_SHEET_ROW TEST APS
1 MX1 MB_SHEET_ROW DEV APT
1 MX_NEW MB_SHEET_ROW NEW_ENTRY APU
1 MX120 MB_SHEET_ROW PROD APV
1 MX5 MB_SHEET_ROW SET APW
1 MX6 MB_SHEET_ROW CHECK APX
1 MX54 MB_SHEET_ROW WHILE APY
1 MX14 MB_SHEET_ROW DO APZ
1 MX2 MB_SHEET_ROW FOR AQA
如何在oracle中自动执行此过程,以便插入中间的每一行都将COL_LOC
移动到excel中的下一列。
我使用此查询来查找与列位置对应的列号。但我不知道如何更新列位置以指向下一列。
SELECT MXP_ID, MX_ID , TB_SRC , DESC, COL_LOC ,
To_Number(
case substr(COL_LOC,1,1)
when 'A' then 1
when 'B' then 2
when 'C' then 3
when 'D' then 4
when 'E' then 5
when 'F' then 6
when 'G' then 7
when 'H' then 8
when 'I' then 9
when 'J' then 10
when 'K' then 11
when 'L' then 12
when 'M' then 13
when 'N' then 14
when 'O' then 15
when 'P' then 16
when 'Q' then 17
when 'R' then 18
when 'S' then 19
when 'T' then 20
when 'U' then 21
when 'V' then 22
when 'W' then 23
when 'X' then 24
when 'Y' then 25
when 'Z' then 26
End ||
case substr(COL_LOC,2,1)
when 'A' then 27
when 'B' then 28
when 'C' then 29
when 'D' then 30
when 'E' then 31
when 'F' then 32
when 'G' then 33
when 'H' then 34
when 'I' then 35
when 'J' then 36
when 'K' then 37
when 'L' then 38
when 'M' then 39
when 'N' then 40
when 'O' then 41
when 'P' then 42
when 'Q' then 43
when 'R' then 44
when 'S' then 45
when 'T' then 46
when 'U' then 47
when 'V' then 48
when 'W' then 49
when 'X' then 50
when 'Y' then 51
when 'Z' then 52
End ||
case substr(COL_LOC,3,1)
when 'A' then 52.3
when 'B' then 53
when 'C' then 54
when 'D' then 55
when 'E' then 56
when 'F' then 57
when 'G' then 58
when 'H' then 59
when 'I' then 60
when 'J' then 61
when 'K' then 62
when 'L' then 63
when 'M' then 64
when 'N' then 65
when 'O' then 66
when 'P' then 67
when 'Q' then 68
when 'R' then 69
when 'S' then 70
when 'T' then 71
when 'U' then 72
when 'V' then 73
when 'W' then 74
when 'X' then 75
when 'Y' then 76
when 'Z' then 77
End) as Column_number
FROM MyTable
order by Column_number;
答案 0 :(得分:0)
问题的核心似乎是我们需要将值从一个数字系统(整数,数字)转换为另一个(列名,字母),因为我们不能只将“加1”添加到一系列列名中为了像电子表格中那样“将它们移到右边”。为了执行转换,我建议使用2个函数。 (警告:以下代码只是粗略的0.01版本!)
-- take a spreadsheet column name
-- find and return an integer that represents the column's position
-- eg 'A' -> 1, 'Z'-> 26, 'AA' -> 27, 'AMJ' -> 1024
create or replace function alphaToInt( colname varchar2 )
return number
is
alphabet constant varchar2( 26 ) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
numberbase number := 26 ;
lettervalue number := 0 ;
currentletter varchar2( 1 ) := '' ;
currentpos number := 0 ;
posval number := 0 ;
result number := 0 ;
begin
for i in 1 .. length( colname )
loop
currentletter := substr( colname, i * -1, 1 ) ;
currentpos := instr( alphabet, currentletter ) ;
posval := power( numberbase, i - 1 ) ;
result := result + ( posval * currentpos ) ;
end loop;
return result ;
end;
/
-- SQL> select alphaToInt( 'AA' ) from dual ;
-- ALPHATOINT('AA')
-- ----------------
-- 27
对于反向操作,您可以使用类似......
的内容-- take an integer
-- find and return its corresponding spreadsheet column name
create or replace function intToAlpha( colnumber number )
return varchar2
is
base number := 26 ;
remaining number := colnumber ;
remainder number := 0 ;
resultstring varchar2( 4000 ) := '' ;
begin
while remaining > 0
loop
remainder := mod( remaining - 1, base ) ;
resultstring := chr( 65 + remainder ) || resultstring ;
remaining := trunc( ( remaining - remainder ) / base ) ;
end loop;
return resultstring ;
end;
/
-- SQL> select intToAlpha( 1024 ) from dual ;
-- INTTOALPHA(1024)
-- -----------------
-- AMJ
测试表
create table mytable (
mxp_id number
, mx_id varchar2( 64 )
, tb_src varchar2( 64 )
, descr varchar2( 64 )
, col_loc char(3)
);
insert into mytable( mxp_id, mx_id, tb_src, descr, col_loc)
select 1 as MXP_ID, 'MX3' as MX_ID, 'MB_SHEET_ROW' as TB_SRC
, 'TEST' as DESCR, 'APS' as COL_LOC from dual union all
select 1, 'MX1', 'MB_SHEET_ROW', 'DEV', 'APT' from dual union all
select 1, 'MX120', 'MB_SHEET_ROW', 'PROD','APU' from dual union all
select 1, 'MX5', 'MB_SHEET_ROW', 'SET', 'APV' from dual union all
select 1, 'MX6', 'MB_SHEET_ROW', 'CHECK','APW' from dual union all
select 1, 'MX54', 'MB_SHEET_ROW', 'WHILE','APX' from dual union all
select 1, 'MX14', 'MB_SHEET_ROW', 'DO', 'APY' from dual union all
select 1, 'MX2', 'MB_SHEET_ROW', 'FOR', 'APZ' from dual;
我们现在有以下情况:
SQL> select * from mytable ;
MXP_ID MX_ID TB_SRC DESCR COL_LOC
1 MX3 MB_SHEET_ROW TEST APS
1 MX1 MB_SHEET_ROW DEV APT
----------------------------------------- <-- want to insert here.
1 MX120 MB_SHEET_ROW PROD APU
1 MX5 MB_SHEET_ROW SET APV
1 MX6 MB_SHEET_ROW CHECK APW
1 MX54 MB_SHEET_ROW WHILE APX
1 MX14 MB_SHEET_ROW DO APY
1 MX2 MB_SHEET_ROW FOR APZ
不确定MX_ID列是否包含唯一值。因此,添加一个id列以便进行测量。
alter table mytable
add id_ raw( 16 ) default sys_guid() ;
-- Table MYTABLE altered.
以下MERGE使用我们的函数,并在“APU”列之后更改所有col_locs。
merge into mytable M
using (
select id_, mxp_id, mx_id, tb_src, descr, col_loc
from mytable
where col_loc >= 'APU'
) M2
on ( M.id_ = M2.id_ )
when matched then
update set col_loc = inttoalpha( alphatoint( col_loc ) + 1 )
;
-- 6 rows merged.
您可能知道数据库表的行不像电子表格的行那样“排序”。在插入新行时请记住这一点。
insert into mytable ( mxp_id, mx_id, tb_src, descr, col_loc )
values ( 1, 'MX_NEW(!)', 'MB_SHEET_ROW', 'NEW_ENTRY', 'APU' ) ;
-- 1 row inserted.
该表现在包含:
select * from mytable order by col_loc;
MXP_ID MX_ID TB_SRC DESCR COL_LOC ID_
1 MX3 MB_SHEET_ROW TEST APS 6CD1B226D8CE12DAE0530100007F80CA
1 MX1 MB_SHEET_ROW DEV APT 6CD1B226D8CF12DAE0530100007F80CA
1 MX_NEW(!) MB_SHEET_ROW NEW_ENTRY APU 6CD1B226D8D612DAE0530100007F80CA
1 MX120 MB_SHEET_ROW PROD APV 6CD1B226D8D012DAE0530100007F80CA
1 MX5 MB_SHEET_ROW SET APW 6CD1B226D8D112DAE0530100007F80CA
1 MX6 MB_SHEET_ROW CHECK APX 6CD1B226D8D212DAE0530100007F80CA
1 MX54 MB_SHEET_ROW WHILE APY 6CD1B226D8D312DAE0530100007F80CA
1 MX14 MB_SHEET_ROW DO APZ 6CD1B226D8D412DAE0530100007F80CA
1 MX2 MB_SHEET_ROW FOR AQA 6CD1B226D8D512DAE0530100007F80CA
使用2个函数,添加新的电子表格列时只需要MERGE和INSERT。你可以写一个小程序,为你做两个步骤。