需求说明
有时候,经常需要将excel表格中数据,转化成sql,方便在数据库中进行灵活的查询。
比如,如下是从excel表格中复制出的数据:
NAME AGE RANK
paopao 5 6
kobe 45 1
tim 36 2
park 35 4
james 35 7
westbrook 32 99
如果将其转化成sql脚本,放到数据库中,就可以方便地进行查询:
-- NAME AGE RANK
select 'paopao' NAME, '5' AGE, '6' RANK from dual union all
select 'kobe' NAME, '45' AGE, '1' RANK from dual union all
select 'tim' NAME, '36' AGE, '2' RANK from dual union all
select 'park' NAME, '35' AGE, '4' RANK from dual union all
select 'james' NAME, '35' AGE, '7' RANK from dual union all
select 'westbrook' NAME, '32' AGE, '99' RANK from dual
VimScript实现
首先实现一个函数,用于将给一行数据添加列:
" combine the column value list with column name, adding prefix and suffix
function! CombineColumnValueAndName(valList, prefix, colList, suffix)
let resultStr = ''
let i = 0
for colValue in a:valList
let resultStr = resultStr . "\'" . colValue . "\' " . a:colList[i] . ", "
let i = i + 1
endfor
" remove the last ', ' at the end
let resultStr = strpart(resultStr, 0, strlen(resultStr) - 2)
return a:prefix . resultStr . a:suffix
endfunction
然后,定义一个函数,读取整个缓冲区的内容,然后逐行处理:
" convert the buffer into select-from-dual clause
function! GenerateSelectFromDual()
" read all the buffer
let allLines = []
g/$/let line = getline(".") | call add(allLines, line)
let resultLines = []
" get all column names into a list. split by \t and keep empty
let colNameList = split(allLines[0], '\t', 1)
" add column names into result comment, split by space
call add(resultLines, '-- ' . join(colNameList, ' '))
" convert line by line
let index = 1
while index < len(allLines)
let curLine = allLines[index]
let valList = split(curLine, '\t', 1)
call add(resultLines, CombineColumnValueAndName(valList, "select ", colNameList, " from dual union all"))
let index = index + 1
endwhile
let resultStr = join(resultLines, "\n")
let @u = strpart(resultStr, 0, strlen(resultStr) - 10)
normal! ggdG
normal! 0"up
return ''
endfunction
最后定义一个自定义的命令,来调用这个函数:
command GenerateSelectFromDual exec GenerateSelectFromDual()
效果
将前面提到的三段vimscript脚本,添加到.vimrc
文件中,source $MYVIMRC
生效后。执行命令:GenerateSelectFromDual
就可以达到前面需求章节描述的效果(支持某些列为空的情况)。
转换前:
NAME AGE RANK
paopao 5 6
kobe 45 1
kobe 1
tim 36 2
Tim 36
park 35 4
35 4
james 35 7
westbrook 32 99
转换后:
-- NAME AGE RANK
select 'paopao' NAME, '5' AGE, '6' RANK from dual union all
select 'kobe' NAME, '45' AGE, '1' RANK from dual union all
select 'kobe' NAME, '' AGE, '1' RANK from dual union all
select 'tim' NAME, '36' AGE, '2' RANK from dual union all
select 'tim' NAME, '36' AGE, '' RANK from dual union all
select 'park' NAME, '35' AGE, '4' RANK from dual union all
select '' NAME, '35' AGE, '4' RANK from dual union all
select 'james' NAME, '35' AGE, '7' RANK from dual union all
select '' NAME, '' AGE, '' RANK from dual union all
select 'westbrook' NAME, '32' AGE, '99' RANK from dual
效果如下:
参考资料
主要参考vim自带的帮助系统,比如:help add
查看add函数的帮助,通过Ctrl+]
可以跳转到指定关键字的章节,通过Ctrl+o
可以跳转回刚才的位置,通过Ctrl+i
可以在历史位置列表中往前跳转。