我正在尝试在psql中执行.sql文件(通过.bat脚本),将 B1 和 B2 中包含的值作为参数传递给< strong> test.xlsm 工作簿。我一直在寻找可能的解决方案,但我无法理解如何在.sql文件中引用这些值(Excel中的单元格B1和B2)。
这是我到目前为止所做的工作。
download_from_postgresql.bat 文件包含以下脚本,以便建立连接并通过psql.exe运行上面提到的download_view.sql文件:
@echo off
setlocal
set PGPASSWORD=mypassword
"D:\PostgreSQL\10\bin\psql.exe" -h myserver.com -U myuser -d mydb -f C:/QA_nepal/download_view.sql
endlocal
download_view.sql 文件包含以下脚本,以便导出直接在我连接的PostgreSQL服务器上创建的特定视图的.csv文件:
\copy (SELECT * FROM public_qa_stfc_india."join_tables_date_filter=custom_user_filter=none") to 'C:\\QA_nepal\\test.csv' with CSV HEADER;
\q
我所指的 join_tables_date_filter = custom_user_filter = none 视图是直接在我的PostgreSQL服务器上创建的,如下所示:
SELECT * FROM public_qa_stfc_india.step_3_joined_tables
WHERE "left"(step_3_joined_tables._0_general_start, 10) >= '2018-05-03'::text
AND "left"(step_3_joined_tables._0_general_start, 10) <= '2018-05-04'::text;
我想要做的是编辑上面包含的视图定义,以便具有以下内容:
SELECT * FROM public_qa_stfc_india.step_3_joined_tables
WHERE "left"(step_3_joined_tables._0_general_start, 10) >= 'date_par_1'::text
AND "left"(step_3_joined_tables._0_general_start, 10) <= 'date_par_2'::text;
并将单元格B1的值传递给date_par_1,将B2的值传递给date_par_2。我所指的Excel工作簿位于C:\ QA_nepal \ excel \ test.xlsm。
此时我不确定如何继续。我应该指示psql从Excel中读取这些值吗?所以在download_from_postgresql.bat中添加说明?或者我应该以某种方式直接在download_view.sql文件中引用Excel中的值?
提前感谢您的帮助, 斯特凡诺
更新2018/06/19
我设法在VB中编写一个宏,能够将单元格B1和B2中的值(值分别为2018-01-01和2015-02-07)传递给.bat文件:
Sub batch()
Dim wsh As Object
Dim data_1 As String
Dim data_2 As String
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
data_1 = ThisWorkbook.Sheets("Foglio1").Range("B1").Value
data_2 = ThisWorkbook.Sheets("Foglio1").Range("B2").Value
wsh.Run "C:\QA_nepal\download_from_postgresql.bat " & data_1 & " " & data_2, windowStyle, waitOnReturn
End Sub
现在我的 download_from_postgresql.bat 文件如下所示:
@echo off
SET data_1=%1%
SET data_2=%2%
ECHO %data_1% 'test if the value in B1 is passed to the .bat file correctly
ECHO %data_2% 'test if the value in B2 is passed to the .bat file correctly
setlocal
set PGPASSWORD=mypassword
"D:\PostgreSQL\10\bin\psql.exe" -h myserver.com -U myuser -d mydb -v v1=%data_1% -v v2=%data_2% -f C:/QA_nepal/download_view.sql
endlocal
此时,我不确定如何在 download_view.sql 中引用变量 v1 和 v2 :< / p>
\copy (SELECT * FROM public_qa_stfc_india."join_tables_date_filter=custom_user_filter=none") to 'C:\\QA_nepal\\test.csv' with CSV HEADER;
\q
考虑到我的 join_tables_date_filter = custom_user_filter = none 视图如下所示:
SELECT * FROM public_qa_stfc_india.step_3_joined_tables
WHERE "left"(step_3_joined_tables._0_general_start, 10) >= '2018-05-03'::text
AND "left"(step_3_joined_tables._0_general_start, 10) <= '2018-05-04'::text;
我知道我必须在上面的视图中用2个变量替换日期('2018-05-03'和'2018-05-04')(让我们说var1和var2)然后我必须“连接” “这些变量(var1和var2)与.bat文件中的变量(v1和v2)我尝试了不同的方式,例如:
\copy (SELECT * FROM public_qa_stfc_india."join_tables_date_filter=custom_user_filter=none" WHERE var1 = (:v1) AND var2 = (:v2)) to 'C:\\QA_nepal\\test.csv' with CSV HEADER;
\q
和
SELECT * FROM public_qa_stfc_india.step_3_joined_tables
WHERE "left"(step_3_joined_tables._0_general_start, 10) >= '$var1'::text
AND "left"(step_3_joined_tables._0_general_start, 10) <= '$var2'::text;
但没有成功。我实际上对SQL很新,所以我可能会走错路。有什么建议吗?
提前致谢, 斯特凡诺
答案 0 :(得分:1)
请考虑使用功能来接收参数并使用string format运行COPY
命令来替换存储的视图,其中该视图的硬编码日期和不接收参数。然后让psql
调用该函数。
CREATE OR REPLACE FUNCTION my_date_filter_func(start_dt TEXT, end_dt TEXT, csv_file TEXT)
RETURNS void AS
$func$
BEGIN
EXECUTE format('COPY (SELECT * FROM public_qa_stfc_india.step_3_joined_tables s
WHERE LEFT(s._0_general_start, 10) >= %L
AND LEFT(s._0_general_start, 10) <= %L) TO %L with CSV HEADER;',
start_dt, end_dt, csv_file);
END
$func$ LANGUAGE plpgsql;
通过 VBA shell调用psql 命令
...
path = "C:/QA_nepal/test.csv"
cmd_str = "psql ... -c ""SELECT my_date_filter_func('" & data_1 & "', '" & data_2 & "', '" & path & "')"""
wsh.Run cmd_str, windowStyle, waitOnReturn
最后,我们不清楚为什么要将日期字段用LEFT()
当作文本,因为您可以直接在WHERE
子句中使用日期文字,并且将时间戳隐式定义为午夜:00:00:00
。 / p>
SELECT *
FROM public_qa_stfc_india.step_3_joined_tables s
WHERE s._0_general_start >= '2018-05-03'
AND s._0_general_start <= '2018-05-04';