【问题标题】:How to extract one query at a time from an SQL file?如何从 SQL 文件中一次提取一个查询?
【发布时间】:2017-04-22 00:33:56
【问题描述】:

我正在尝试从 SQL 文件中一次提取一个查询。

这是我尝试过的

index1=1
index2=1
while read -n1 char; do
if [[ $char == ";" ]]
  then
     SUBSTRING=$(awk 'substr($index1,$index2)' sql1Temp.sql)
     echo $SUBSTRING 
    index1=$index2
fi 
((index2+=1))

done <sql1Temp.sql

我的 SQL 文件如下所示:

sql1Temp.sql
从 test1 中选择 *;
从 test2 中选择 *;
从 test3 中选择 *;

结果我得到了这个:

wedtorque@wedtorque-VirtualBox:~/Desktop$ ./masterFile.sh
select *from test1; select *from test2; select *from test3;
select *from test1; select *from test2; select *from test3;
select *from test1; select *from test2; select *from test3;
wedtorque@wedtorque-VirtualBox:~/Desktop$

而我期待这样的事情:

wedtorque@wedtorque-VirtualBox:~/Desktop$ ./masterFile.sh
select *from test1;
select *from test1;
select *from test1;
wedtorque@wedtorque-VirtualBox:~/Desktop$

此外,当我在 while 循环中回显 $char 时,它会在每次 $char 从查询中获取 * 时打印文件名,select *from test1;等等

类似的东西

wedtorque@wedtorque-VirtualBox:~/Desktop$ ./masterFile.sh
s
e
l
e
c
t

masterFile.sh sql1result.sql sql1.sql sql1Temp.sql sql2.sql Untitled Document
f
r
o
m

t
e
s
t
1
select *from test1; select *from test2; select *from test3;
; 
same thing 3 times 

我认为 awk 有什么问题?

【问题讨论】:

  • 您能否解释一下您的脚本的用途,按照我的阅读方式,它似乎是一种类似于cat sql1Temp.sql 的复杂而缓慢的方式,我想一定有什么我失踪了。
  • 我需要从 sql1Temp.sql 文件中获取一个 sql 查询,执行它然后将此查询复制到一个新文件并从原始文件中删除该查询。
  • 每行是否始终只有一条 SQL 语句,或者您是否需要处理可能有多个 SQL 语句(用分号分隔)的情况?
  • 我需要用 ; 分隔.我的sql文件包含多行查询以分号结尾。下一个查询以新行开始

标签: sql bash unix awk substr


【解决方案1】:

您需要做的只是逐行读取文件,这可以在没有awk 的情况下以更简单的方式完成:

while IFS= read -r line; do
  echo "$line" # Or do what you need to do (e.g. execute SQL statement)
done <sql1Temp.sql

您不必担心分号,因为read 语句一次读取一行,每行读取一条语句。

如果你想删除成功执行的执行语句,你可以这样做:

local statements="sql1Temp.sql"
local failed="sql1Temp.sql.failed"
while IFS= read -r line; do
  if
    ! SOME_SQL_UTILITY "$line"
  then
    echo "$line" >>"$failed"
  fi
done <"$statements"
[[ ! -f "$failed" ]] || mv -f "$failed" "$statements"

基本上,创建一个包含失败语句的新文件,然后移动新文件以覆盖旧文件,除非新文件不存在。

请注意! SOME_SQL_UTILITY "$line" 中的! 表示“认为此命令失败意味着测试成功”(本质上是一个非逻辑运算符)。

另外,我在上面的代码中使用了echo 以使其尽可能熟悉,但使用printf 可以确保没有特殊字符序列触发意外的shell 行为。用这个替换上面的行:

printf "%s" "$line" >>"$failed"

最后,您可以通过使用逻辑运算符而不是 if 块来进一步缩短代码:

#!/bin/bash
local statements="sql1Temp.sql"
local failed="sql1Temp.sql.failed"
while IFS= read -r line; do
  SOME_SQL_UTILITY "$line" || printf "%s" "$line" >>"$failed"
done <"$statements"
[[ ! -f "$failed" ]] || mv -f "$failed" "$statements"

我还包含了“shebang”以允许将此脚本作为可执行文件启动。使用逻辑 || (OR) 运算符并不比使用 if 语句更好,只有在您理解它并且更喜欢它的情况下才这样做。

【讨论】:

  • 你应该把它作为一个单独的问题发布。
  • 如何从 sql1Temp.sql 中删除 $line(single query)。将其复制到新文件后
  • 您是否希望sql1Temp.sql 在您完成处理后为空,或者某些行会根据某些条件保留在文件中?
  • sql1Temp.sql 将有剩余的执行失败的 sql 查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-22
  • 2020-09-26
相关资源
最近更新 更多