我写了一个小脚本来复制SQL服务器之间的表。 它有效,但其中一列将类型从varchar更改为text ... 如何使其复制具有相同列类型的表?
import pymssql
import pandas as pd
from sqlalchemy import create_engine
db_server= 1.2.3.4\\r2
db_database="Test_DB"
db_user="vaf"
db_password="1234"
local_db_server="1.1.1.1\\r2"
local_db_database="Test_DB"
local_db_user="vaf"
local_db_password="1234"
some_query=("""
select * from some_table
""")
def main():
conn=pymssql.connect(server=local_db_server,user=local_db_user,password=local_db_password,database=local_db_database,charset='UTF-8')
data=pd.io.sql.read_sql(some_query,conn)
connection_string='mssql+pymssql://{}:{}@{}/{}'.format(db_user,db_password,db_server,db_database)
engine=create_engine(connection_string)
data.to_sql(name="some_table",con=engine,if_exists='replace',index=False)
if __name__ == "__main__":
main()
由于
答案 0 :(得分:8)
考虑三种方法:
指定类型 (预测未来会主动)
使用pandas.DataFrame.to_sql
的 dtype 参数,为命名列传递sqlalchemy types字典。
data.to_sql(name="some_table", con=engine, if_exists='replace', index=False,
dtype={'datefld': sqlalchemy.DateTime(),
'intfld': sqlalchemy.types.INTEGER(),
'strfld': sqlalchemy.types.VARCHAR(length=255),
'floatfld': sqlalchemy.types.Float(precision=3, asdecimal=True),
'booleanfld': sqlalchemy.types.Boolean}
删除数据 (提前预测)
使用DELETE
操作查询清理表格。然后,仅将pandas中的数据迁移到SQL Server,而不会在结构上更改表,因为to_sql
replace 参数会重新创建表。此方法假定数据帧始终与数据库表一致(没有新列/更改的类型)。
def main():
connection_string = 'mssql+pymssql://{}:{}@{}/{}'\
.format(db_user,db_password,db_server,db_database)
engine = create_engine(connection_string)
# IMPORT DATA INTO DATA FRAME
data = pd.read_sql(some_query, engine)
# SQL DELETE (CLEAN OUT TABLE) VIA TRANSACTION
with engine.begin() as conn:
conn.execute("DELETE FROM some_table")
# MIGRATE DATA INTO DATA FRAME (APPEND NOT REPLACE)
data.to_sql(name='some_table', con=engine, if_exists='append', index=False)
MODIFY COLUMN (因为它修复了ad-hoc)
使用DDL SQL语句在迁移后更改列。
def main():
connection_string = 'mssql+pymssql://{}:{}@{}/{}'\
.format(db_user,db_password,db_server,db_database)
engine = create_engine(connection_string)
# IMPORT DATA INTO DATA FRAME
data = pd.read_sql(some_query, engine)
# MIGRATE DATA INTO DATA FRAME
data.to_sql(name="some_table", con=engine, if_exists='replace', index=False)
# ALTER COLUMN TYPE (ASSUMING USER HAS RIGHTS/PRIVILEGES)
with engine.begin() as conn:
conn.execute("ALTER TABLE some_table ALTER COLUMN mytextcolumn VARCHAR(255);")
我推荐第二种方法,因为我认为数据库应该与python和pandas等应用程序代码无关。因此,表模式的初始构建/重新构建应该是一个计划的手动过程,并且任何脚本都不应该在结构上动态地更改数据库,只与数据交互。