如何批量执行包含圆括号的postgres Select语句?
How to do a postgres Select statement which contains round brackets in a batch?
我正在尝试通过批处理文件对 postgres 数据库执行 select。
postgres 数据库提供了一个命令行界面 (psql),您可以在其中输入数据库命令,这些命令在这里是在 for 循环中完成的。看看 pg_cmd 是如何拼接在一起的。 select pd_SelCmd 回显到 pg_SelCall。
在 for 语句中执行命令,但由于 select 包含圆括号,它们会导致错误解释和错误:
"FROM"此时无法进行句法处理。
如何转义圆括号以使请求正常工作?
DB 的预期响应如下所示:
max
-------------------------
2016-12-29 09:40:09.842
(1 Line)
目前使用的批次是这个
setlocal enabledelayedexpansion
Set "PgRootPath=C:\Program Files\PostgreSql.5.5-1\bin"
Call :GetDoneTime 56665454 DONE_TIME
echo = DONE_TIME=!DONE_TIME!
Goto :EOF
:GetDoneTime
set "ERRORLEVEL="
set "MC_UID=%~1"
set "ReturnDoneTimeValueRef=%~2"
set "DataVal=NULL"
set "PGPASSWORD=frontenduser"
set "PGCLIENTENCODING=utf-8"
set pd_SelCmd=SELECT max(t.endDate) FROM Ticket t JOIN Device d on t.device_id = d.id WHERE t.state in ('APPROVED','IN_PROGRESS', 'IN_ACTIVITY') AND d.uid='!MC_UID!';
set pg_SelCall="!PgRootPath!\psql" -U frontenduser -h localhost -d ppsdb
REM if call to psql produces an fatal error, the error number will be passed to for loop on third parameter in third line
set pg_cmd="echo !pd_SelCmd! | !pg_SelCall! || echo/ & echo/ & call echo NULL NULL %%^^^errorlevel%%"
set "pg_cmd=!pg_cmd:)=^)!"
REM Execute PG command. Resulting DataValue obtained from third row
REM Check for errors of call
for /f "skip=2 tokens=1,2,3" %%i in ('!pg_cmd!') do (
REM Get value in first and second parameter from split - which is from third row
set "DataVal=%%i %%j"
REM If error happend, report it. Error code is obtained in 3rd parameter.
if "!DataVal!"=="NULL NULL" (
echo ## Postgres DB operation failed with ERROR: %%~k
set "DataVal=NULL"
) else (
REM Check if result is not valid
if "!DataVal:~0,1!"=="(" set "DataVal=NULL"
)
goto GotDoneTime
)
:GotDoneTime
if not '!ReturnDoneTimeValueRef!'=='' set "!ReturnDoneTimeValueRef!=!DataVal!"
if "!DataVal!"=="NULL" exit /b 1
exit /b 0
这里只是一些错误。不幸的是,我不知道 postgresql,也没有必要的数据库,所以我无法测试它,但是这里是...
首先,代码块(带括号的语句系列)中不允许使用标签,::
是损坏的标签。在一个代码块中,应使用rem
进行注释。
接下来,将 for
循环中的 '!pg_cmd!
替换为 type q41353737.txt
(其中 q41353737.txt
是包含您发布的命令的预期数据输出的文件)然后dataval
设置为 09:40:09.842
BUT 由于文件中有第四行,下一行也将被处理并设置 dataval
至 Line)
.
要解决这个问题,您只需将其更改为
rem If error happened, report it. Error code is obtained in 3rd parameter.
if not '%%~k'=='' echo ## Postgres DB operation failed with ERROR: %%~k
rem If operation succeeded, get value in second parameter from split - which is from second data column
if '%%~k'=='' SET DataVal=%%~j
goto done
)
:done
因此只处理第三行,然后 for
循环被毫不客气地终止。
下一个问题是您投诉的问题。 )
正在终止 for ... (
,因此您需要告诉 cmd
那个特定的 )
是 要执行的命令的一部分 , 不是 for
, 所以你需要用插入符号转义它 ((
变成 ^)
)
最简单的方法大概就是在for
之前加一行
set "pg_cmd=!pg_cmd:)=^)!"
应该在命令中适当地为所有 )
添加必要的插入符号前缀。
我怀疑您还会遇到其他问题字符的问题,因此可能需要对 |
应用类似的过程,即
set "pg_cmd=!pg_cmd:|=^|!"
这是我必须离开的地方,因为我无法正确执行命令本身。
我正在尝试通过批处理文件对 postgres 数据库执行 select。 postgres 数据库提供了一个命令行界面 (psql),您可以在其中输入数据库命令,这些命令在这里是在 for 循环中完成的。看看 pg_cmd 是如何拼接在一起的。 select pd_SelCmd 回显到 pg_SelCall。 在 for 语句中执行命令,但由于 select 包含圆括号,它们会导致错误解释和错误: "FROM"此时无法进行句法处理。
如何转义圆括号以使请求正常工作?
DB 的预期响应如下所示:
max
-------------------------
2016-12-29 09:40:09.842
(1 Line)
目前使用的批次是这个
setlocal enabledelayedexpansion
Set "PgRootPath=C:\Program Files\PostgreSql.5.5-1\bin"
Call :GetDoneTime 56665454 DONE_TIME
echo = DONE_TIME=!DONE_TIME!
Goto :EOF
:GetDoneTime
set "ERRORLEVEL="
set "MC_UID=%~1"
set "ReturnDoneTimeValueRef=%~2"
set "DataVal=NULL"
set "PGPASSWORD=frontenduser"
set "PGCLIENTENCODING=utf-8"
set pd_SelCmd=SELECT max(t.endDate) FROM Ticket t JOIN Device d on t.device_id = d.id WHERE t.state in ('APPROVED','IN_PROGRESS', 'IN_ACTIVITY') AND d.uid='!MC_UID!';
set pg_SelCall="!PgRootPath!\psql" -U frontenduser -h localhost -d ppsdb
REM if call to psql produces an fatal error, the error number will be passed to for loop on third parameter in third line
set pg_cmd="echo !pd_SelCmd! | !pg_SelCall! || echo/ & echo/ & call echo NULL NULL %%^^^errorlevel%%"
set "pg_cmd=!pg_cmd:)=^)!"
REM Execute PG command. Resulting DataValue obtained from third row
REM Check for errors of call
for /f "skip=2 tokens=1,2,3" %%i in ('!pg_cmd!') do (
REM Get value in first and second parameter from split - which is from third row
set "DataVal=%%i %%j"
REM If error happend, report it. Error code is obtained in 3rd parameter.
if "!DataVal!"=="NULL NULL" (
echo ## Postgres DB operation failed with ERROR: %%~k
set "DataVal=NULL"
) else (
REM Check if result is not valid
if "!DataVal:~0,1!"=="(" set "DataVal=NULL"
)
goto GotDoneTime
)
:GotDoneTime
if not '!ReturnDoneTimeValueRef!'=='' set "!ReturnDoneTimeValueRef!=!DataVal!"
if "!DataVal!"=="NULL" exit /b 1
exit /b 0
这里只是一些错误。不幸的是,我不知道 postgresql,也没有必要的数据库,所以我无法测试它,但是这里是...
首先,代码块(带括号的语句系列)中不允许使用标签,::
是损坏的标签。在一个代码块中,应使用rem
进行注释。
接下来,将 for
循环中的 '!pg_cmd!
替换为 type q41353737.txt
(其中 q41353737.txt
是包含您发布的命令的预期数据输出的文件)然后dataval
设置为 09:40:09.842
BUT 由于文件中有第四行,下一行也将被处理并设置 dataval
至 Line)
.
要解决这个问题,您只需将其更改为
rem If error happened, report it. Error code is obtained in 3rd parameter.
if not '%%~k'=='' echo ## Postgres DB operation failed with ERROR: %%~k
rem If operation succeeded, get value in second parameter from split - which is from second data column
if '%%~k'=='' SET DataVal=%%~j
goto done
)
:done
因此只处理第三行,然后 for
循环被毫不客气地终止。
下一个问题是您投诉的问题。 )
正在终止 for ... (
,因此您需要告诉 cmd
那个特定的 )
是 要执行的命令的一部分 , 不是 for
, 所以你需要用插入符号转义它 ((
变成 ^)
)
最简单的方法大概就是在for
之前加一行
set "pg_cmd=!pg_cmd:)=^)!"
应该在命令中适当地为所有 )
添加必要的插入符号前缀。
我怀疑您还会遇到其他问题字符的问题,因此可能需要对 |
应用类似的过程,即
set "pg_cmd=!pg_cmd:|=^|!"
这是我必须离开的地方,因为我无法正确执行命令本身。