2016-11-30 28 views
1

我正在編寫一個針對Microsoft SQL Server 2012實例的Python數據庫數據備份腳本。我的目標是能夠輕鬆地將數據庫的數據備份到現有的空模式。我使用pymssql作爲我的數據庫接口。使用fetchall轉換查詢結果類型()

這裏是我有問題的代碼段:

def run_migrate(s_conn, d_conn): 
    source_cursor = s_conn.cursor() 
    dest_cursor = d_conn.cursor() 
    source_cursor.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES order by TABLE_NAME asc") 
    res_tables = source_cursor.fetchall() 
    tables = [i[0] for i in res_tables] 
    for i in range(len(tables)): 
     query_columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + str(tables[i]) + "'" 
     l.log.debug(query_columns) 
     source_cursor.execute(query_columns) 
     res_columns = source_cursor.fetchall() 
     columns = [i[0] for i in res_columns] 
     query_data = 'SELECT * FROM ' + tables[i] 
     l.log.debug(query_data) 
     source_cursor.execute(query_data) 
     res_results = source_cursor.fetchall() 
     l.log.info('Extracted ' + str(len(results)) + ' results from ' + tables[i]) 

我的問題是,當我使用res_results = fetchall()我回來,看起來像下面的列表:

<class 'list'>: [(Decimal('102'), datetime.datetime(2016, 3, 29, 13, 53, 20, 593000), '1459281200561077E9152BF85FCBC33E6689E9DCB61705985137701459280466827', 'cable summary ', 3600000, 0, None, None, None, None, None, None, 0, 0, None, None, Decimal('333'), Decimal('100'), Decimal('107'), None, None)] 

我我期待從這些數據中形成一個參數化的INSERT語句,以針對d_conn.execute()運行,但是如何在不事先知道每列數據類型以及如何處理它的情況下即時轉換數據類型?

比如我需要轉換列表:

<class 'list'>: [ 
(Decimal('102'), 
datetime.datetime(2016, 3, 29, 13, 53, 20, 593000), 
'1459281200561077E9152BF85FCBC33E6689E9DCB61705985137701459280466827', 
'cable summary ', 
3600000, 
0, 
None, 
None, 
None, 
None, 
None, 
None, 
0, 
0, 
None, 
None, 
Decimal('333'), 
Decimal('100'), 
Decimal('107'), 
None, 
None)] 

到SQL INSERT語句:

INSERT INTO [ALERT] VALUES 
    (102 
    ,'2016-03-29 13:53:20.593' 
    ,1 
    ,'cable summary' 
    ,3600000 
    ,0 
    ,NULL 
    ,NULL 
    ,NULL 
    ,NULL 
    ,NULL 
    ,NULL 
    ,0 
    ,0 
    ,NULL 
    ,NULL 
    ,333 
    ,100 
    ,107 
    ,NULL 
    ,NULL) 

我希望能夠用我把它當作我的任何數據類型來做到這一點有幾百個表來做到這一點,不想爲每個表寫一個函數。任何幫助表示讚賞。

+0

使用強制和一個ORM,盧克。 sqlalchemy是光明的一面,並支持pymssql。 –

回答

1

例如我將需要轉換列表...進入[文字] SQL INSERT語句...

其實,沒有你不會,至少不會,如果你真的做到了使用INSERT的參數化查詢。 Python的DB-API指定通用參數佔位符,並依靠數據庫訪問層(例如pymssql)根據提供的參數的類型找出如何處理參數。

所以,可以簡單地採取行(其包含適當的類型的值)從源表的列表,並在目標表上使用這些行作爲參數值的executemany,像這樣:

# set up test 
create_stmt = """\ 
CREATE TABLE {} (
    intCol INT PRIMARY KEY, 
    nvarcharCol NVARCHAR(50), 
    datetimeCol DATETIME, 
    decimalCol DECIMAL(18,4), 
    nullableCol INT 
    ) 
""" 
crsr.execute(create_stmt.format("#MainTable")) 
load_test_data = """\ 
INSERT INTO #MainTable (intCol, nvarcharCol, datetimeCol, decimalCol) VALUES 
    (1, N'test 1', '2016-01-01', 1.11), 
    (2, N'test 2', '2016-02-02', 2.22), 
    (3, N'test 3', '2016-03-03', 3.33) 
""" 
crsr.execute(load_test_data) 
crsr.execute(create_stmt.format("#BackupTable")) 

# perform the copy ... 
read_stmt = """\ 
SELECT * FROM #MainTable 
""" 
crsr.execute(read_stmt) 
source_rows = crsr.fetchall() 
# ... using a true parameterized query ... 
write_stmt = """\ 
INSERT INTO #BackupTable 
     (intCol, nvarcharCol, datetimeCol, decimalCol, nullableCol) 
    VALUES 
     (%s, %s, %s, %s, %s) 
""" 
# ... inserting all rows at once using list returned by fetchall() from source table 
crsr.executemany(write_stmt, source_rows) 

#check results 
crsr.execute("SELECT * FROM #BackupTable") 
print("Rows from #BackupTable:") 
for row in crsr.fetchall(): 
    print(row) 

...生產:

Rows from #BackupTable: 
(1, 'test 1', datetime.datetime(2016, 1, 1, 0, 0), Decimal('1.1100'), None) 
(2, 'test 2', datetime.datetime(2016, 2, 2, 0, 0), Decimal('2.2200'), None) 
(3, 'test 3', datetime.datetime(2016, 3, 3, 0, 0), Decimal('3.3300'), None) 
+0

這工作,謝謝你的幫助! – DatumPlane