同一个SQL Server临时表是否可以持久化并由多个独立执行的Python脚本使用,而无需每次重新创建?

同一个SQL Server临时表是否可以持久化并由多个独立执行的Python脚本使用,而无需每次重新创建?,python,sql-server,makefile,pyodbc,Python,Sql Server,Makefile,Pyodbc,我正在从SQLServer数据库获取数据,并将其保存到文件中,以便在Python中进行后续处理 我使用Make自动获取和重新提取数据(如果某些设置发生更改,则只重新运行受影响的部分查询,而不是所有查询)。因此,我有一个简单的Makefile,如下所示: rawdata: datafile1.h5, datafile2.h5 # ... more files like this datafile1.h5: data1_specific_config.py, common_config.py

我正在从SQLServer数据库获取数据,并将其保存到文件中,以便在Python中进行后续处理

我使用Make自动获取和重新提取数据(如果某些设置发生更改,则只重新运行受影响的部分查询,而不是所有查询)。因此,我有一个简单的Makefile,如下所示:

rawdata: datafile1.h5, datafile2.h5 # ... more files like this
datafile1.h5: data1_specific_config.py, common_config.py
    python fetch_data1.py
datafile2.h5: data2_specific_config.py, common_config.py
    python fetch_data2.py
# ... similar rules for other files
需要时,我只需运行
makerawdata

现在,脚本
fetch_dataN.py
执行的所有SQL查询都有一个重要的公共部分。由
fetch_dataN.py
运行的
queryN
示意图如下所示:

select ... into ##common_tmp_table ... /*this is identical for all queries*/
select ... from (... ##common_tmp_table ...) /*this is queryN specific; but the same ##common_tmp_table is used*/
问题是:当我现在运行
makerawdata
时,假设需要重建五个不同的数据文件,那么相同的查询
select。。。在##公共#tmp(表)中运行五次
,并将相同的输出输出到##公共#tmp(表)。查询需要相当长的时间才能运行,因此重新执行它五次会大大降低速度

但是,当一个脚本
fetch_dataN.py
完成时,临时表总是会被删除,因为创建临时表的db连接已终止

问题:

有没有办法强制只创建一次表
##common_tmp_table
,并在所有由
make rawdata
执行的脚本
fetch_dataN.py
之间持久化

特别是,有没有办法在
make rawdata
运行的所有脚本中使用相同的db连接?或者打开一个额外的连接,该连接将在所有脚本运行时保持,并防止删除全局临时表

我知道的解决方法: 我可以通过手动创建
##common_tmp_表
(例如在MS SQL Server Management Studio中)来解决此问题,然后运行
生成原始数据
,并保持用于此的连接打开,直到所有脚本完成。但这显然是丑陋和恼人的

如果
makerawdata
可以打开一个单独的进程来打开一个连接,创建tmp表并一直等待,直到其他一切都完成,这将是一个解决方案。但我不知道这是否可能

限制:

  • 我无法在数据库中进行更改(例如创建永久表而不是临时表)
  • 我需要脚本保持独立,以便make可以独立地执行它们(在一个脚本中使用相同的db连接并因此使用相同的tmp表不会有任何帮助-每当需要重新获取其中一个或两个数据文件时,重建所有数据文件的速度会更慢)
注意事项:

  • MS SQL Server 2008 R2
  • pyodbc 4.0.28
    (用于连接到数据库)
  • python 3.7.6
  • make 4.3
  • conda 4.7.12

谢谢。

所以我找到了一个非常有效的解决方案:想法是让
生成rawdata
执行一个python脚本

  • 打开数据库连接并使其保持打开状态
  • 创建
    ##common_tmp_表
  • 运行负责重建数据文件的
    make rawdata
    (与问题中发布的代码中的
    make rawdata
    相同,但现在没有
    select…进入查询中的###common_tmp_表…
  • 关闭连接
  • 代码:

    生成文件:

    #THIS IS NEW
    .PHONY rawdata # to always rebuild rawdata target
    rawdata:
        python fetch_all_non_uptodate.py # just call a script that (among other stuff) runs `make rawdata_`
    
    #THE REST IS AS BEFORE (just added underscore)
    rawdata_: datafile1.h5, datafile2.h5 # ... more files like this
    datafile1.h5: data1_specific_config.py, common_config.py
        python fetch_data1.py
    datafile2.h5: data2_specific_config.py, common_config.py
        python fetch_data2.py
    # ... similar rules for other files
    
    获取_all_non_Update.py:

    import subprocess
    import pyodbc
    
    conn = pyodbc.connect(...) #open db connection
    
    # simulate the run of make with the -q flag to find out whether all the datafiles are up-to-date (return code 0) or not (return code 1); nothing is re-fetched as yet
    uptodate = (subprocess.run(['make', '-q', 'rawdata_']).returncode == 0)
    
    # if the raw datafiles are not up-to-date
    if not uptodate:    
        create_common_tmp_table(conn) # create the ##common_tmp_table in the db and keep it while conn is open
        conn.commit() #commit the creation of the tmp table (Important! - otherwise the other connections won't see it!)
        subprocess.run(['make', 'rawdata_']) # run make to re-fetch whatever datafiles need to be re-fetched
                                             # the queries can make use of the existing tmp table
    # otherwise we just simulate the make output telling that all is up-to-date
    else:
        print("make: Nothing to be done for 'rawdata'.")
    
    conn.close()
    
    克林:

    /*keep just the specific part - the ##common_tmp_table already exists*/
    select ... from (... ##common_tmp_table ...)
    

    听起来你已经找到了解决办法——让一个过程打开一个连接,创建###common#tmp#表,完成生成过程,等待它完成,最后关闭连接。谢谢你的评论和鼓励——我认为这可能是一种方法,但不确定它是否正确。仍然想知道是否有更“直接”的解决方案。。有点希望在makefile中进行一些简单的黑客攻击,从而自动完成任务:-)。