我正在运行一个带有sqlalchemy的python脚本来导出,然后每天将数据从生产导入到postgres数据库中。该脚本成功运行一次,然后第二次超出脚本失败。正如您将在下面的脚本中看到的,返回的错误表明表中的依赖项(外键)是导致导入失败的原因,但是,我不明白为什么abstract class parent
{
private config;
public function __construct()
{
$this->config = "get file";
}
public function getConfig(){
return $this->config;
}
}
class a extends parent
{
private config;
public function __construct(){
$this->config = parent::getConfig();
}
}
对象不会绕过此问题。我选择删除任何初始代码,如repoistory导入,db连接对象,以简化帖子并减少混乱。
sorted_tables
如果在导入数据之前删除整个def create_db(src,dst,src_schema,dst_schema,drop_dst_schema=False):
if drop_dst_schema:
post_db.engine.execute('DROP SCHEMA IF EXISTS {0} CASCADE'.format(dst_schema))
print "Schema {0} Dropped".format(dst_schema)
post_db.engine.execute('CREATE SCHEMA IF NOT EXISTS {0}'.format(dst_schema))
post_db.engine.execute('GRANT USAGE ON SCHEMA {0} TO {0}_ro'.format(dst_schema))
post_db.engine.execute('GRANT USAGE ON SCHEMA {0} TO {0}_rw'.format(dst_schema))
print "Schema {0} Created".format(dst_schema)
def create_table(tbl, dst_schema):
dest_table=tbl
dest_table.schema=dst_schema
for col in dest_table.columns:
if hasattr(col.type, 'collation'):
col.type.collation = None
if col.name == 'id':
dest_table.append_constraint(PrimaryKeyConstraint(col))
col.type=convert(col.type)
timestamp_col=Column ('timestamp',DateTime(timezone=False), server_default=func.now())
#print tbl.c
dest_table.append_column(timestamp_col)
dest_table.create(post_db.engine,checkfirst=True)
post_db.engine.execute('GRANT INSERT ON {1} to {0}_ro'.format(dst_schema, dest_table))
post_db.engine.execute('GRANT ALL PRIVILEGES ON {1} to {0}_rw'.format(dst_schema, dest_table))
print "Table {0} created".format(dest_table)
create_db(mysql_db.engine,post_db.engine,src_schema,dst_schema,drop_dst_schema=False)
mysql_meta=MetaData(bind=mysql_db.engine)
mysql_meta.reflect(schema=src_schema)
post_meta=MetaData(bind=post_db.engine)
post_meta.reflect(schema=dst_schema)
script_begin=time.time()
rejected_list=[]
for table in mysql_meta.sorted_tables:
df=mysql_db.sql_retrieve('select * from {0}'.format(table.name))
df=df.where((pd.notnull(df)), None)
print "Table {0} : {1}".format(table.name,len(df))
dest_table=table
dest_table.schema = dst_schema
dest_table.drop(post_db.engine, checkfirst=True)
create_table(dest_table, dst_schema)
print "Table {0} emptied".format(dest_table.name)
try:
start=time.time()
if len(df)>10000:
for g,df_new in df.groupby(np.arange(len(df))//10000):
dict_items=df_new.to_dict(orient='records')
post_db.engine.connect().execute(dest_table.insert().values(dict_items))
else:
dict_items=df.to_dict(orient='records')
post_db.engine.connect().execute(dest_table.insert().values(dict_items))
loadtime=time.time()-start
print "Data loaded with datasize {0}".format(str(len(df)))
print "Table {0} loaded to BI database with loadtime {1}".format(dest_table.name,loadtime)
except:
print "Table {0} could not be loaded".format(dest_table.name)
rejected_list.append(dest_table.name)
,则导入成功。
这是我看到的那个人:
dst_schema
有人可以引导我找到可能的解决方案吗?
除了在将数据导入目标db sqlalchemy.exc.InternalError: (psycopg2.InternalError) cannot drop table A because other objects depend on it
DETAIL: constraint fk_rails_111193 on table B depends on table A
HINT: Use DROP ... CASCADE to drop the dependent objects too.
[SQL: '\nDROP TABLE A']
之前删除dst_schema
之外,还有其他更好的选择吗?
(drop_dst_schema=true)
有没有人知道为什么def create_db(src,dst,src_schema,dst_schema,drop_dst_schema=True)
不会删除架构中的依赖项?我误解了这个对象吗?
答案 0 :(得分:0)
您有几种选择:
如果您有一个复杂的架构,任何类型的闭环参考链,您最好的选择是始终放弃整个架构。
您可以拥有一些自引用表(例如persons
表,其自身关系类型为person parent-of person
)。您还可以拥有一个模式,其中表A引用引用表A的表B.例如,您有一个表persons
和一个companies
,以及两个关系(可能与中间表一起):{{ 1}}和company employs persons
。
在这种情况下,这是切合实际的,无论你使用persons trade shares of companies
做什么,这都行不通。
如果您实际上是从另一个数据库复制数据,并且能够负担得起时间,那么删除和重新创建整个模式是最容易实现的解决方案。您的代码将更加简单:需要考虑的案例更少。
您也可以使用 sorted_tables
删除表格。如果一个表被另一个表引用,则会同时删除(或根据需要删除多个表)。您必须确保DROP CASCADE
和DROP
的顺序为您提供预期的最终结果。我会非常仔细地检查这种情况是否适用于所有情况。
此外,还有最后一种可能性:在操作它们之前删除所有表的所有FK约束,并在最后重新创建它们。这样,您就可以随时删除任何表格。