เหตุ:
import pymysql
import pandas as pd
import sqlalchemy
import time
import datetime
conn = pymysql.connect(
host="source.database.server",
port=3306,
user='username',
password='password',
database='databasename',
)
sql="""
SELECT *
FROM table1
"""
df1=pd.read_sql(sql,conn)
df1.dtypes
ผลคือ:
.
.
.
ref_visit_date object
ref_visit_time timedelta64[ns]
.
.
.
ซึ่ง ref_visit_time นั้น ใน MySQL/MariaDB ใช้ชนิดเป็น Time
เช่น 08:00:00 หมายถึง 8 นาฬิกา อะไรทำนองนั้น
ปัญหา:
อยู่ที่ตอนเอา Dataframe นี้ ไป Write ใส่อีก Table นึง
host="destination.database.server"
port=int(3306)
user='user'
password='password'
dbname='databasename'
db_string = f"mysql+pymysql://{user}:{password}@{host}:{port}/{dbname}"
destination_conn = sqlalchemy.create_engine(db_string)
df.to_sql('table2'
, con=destination_conn
, if_exists='append'
, index=False
, method='multi'
, chunksize=10000)
ซึ่ง table2 นั้น มีโครงสร้างเหมือนกับ table1 เลย โดยเฉพาะ ref_visit_time มีชนิดเป็น Time เช่นกัน
แต่ถ้า run code นี้จะได้ Error/Warning ว่า
UserWarning: the 'timedelta' type is not supported, and will be written as integer values (ns frequency) to the database.
เหตุเพราะ แทนที่จะเก็บเป็น Time มันดันเปลี่ยนเป็น Integer ที่เป็นจำนวน Nanosecond แทนนั่นเอง
วิธีแก้ไข
ต้องตรวจสอบว่า มี column ใน destination table มีชนิดเป็น Time (timedelta64[ns]) ให้เอาไปบวกกับเวลาเริ่มต้น แล้ว เปลี่ยนชนิดเป็น Time แทน ดังนี้
for column in df:
if df[column].dtype == 'timedelta64[ns]':
df[column]=df[column].apply(lambda x: (datetime.datetime.min+x).time())
เราก็จะได้ข้อมูลที่ถูกต้องกลับมา
ตามนั้นครับ