相关疑难解决方法(0)

如何使用SqlAlchemy进行upsert?

我有一个记录,我希望它存在于数据库中,如果它不存在,如果它已存在(主键存在)我希望字段更新到当前状态.这通常称为upsert.

以下不完整的代码片段演示了什么可行,但它似乎过于笨重(特别是如果有更多的列).什么是更好/最好的方式?

Base = declarative_base()
class Template(Base):
    __tablename__ = 'templates'
    id = Column(Integer, primary_key = True)
    name = Column(String(80), unique = True, index = True)
    template = Column(String(80), unique = True)
    description = Column(String(200))
    def __init__(self, Name, Template, Desc):
        self.name = Name
        self.template = Template
        self.description = Desc

def UpsertDefaultTemplate():
    sess = Session()
    desired_default = Template("default", "AABBCC", "This is the default template")
    try:
        q = sess.query(Template).filter_by(name = desiredDefault.name)
        existing_default = q.one()
    except sqlalchemy.orm.exc.NoResultFound:
        #default does not exist yet, …
Run Code Online (Sandbox Code Playgroud)

python sqlalchemy upsert

54
推荐指数
4
解决办法
3万
查看次数

SQLAlchemy ON DUPLICATE KEY UPDATE

INSERT ... ON DUPLICATE KEY UPDATE在SQLAlchemy中有一种优雅的方式吗?我的意思是语法类似的东西inserter.insert().execute(list_of_dictionaries)

python mysql sqlalchemy

29
推荐指数
2
解决办法
3万
查看次数

空字典作为python函数中关键字参数的默认值:在后续调用中,字典似乎没有被初始化为{}?

这是一个功能.我的意图是使用关键字参数默认值使字典成为空字典(如果未提供).

>>> def f( i, d={}, x=3 ) :
...     d[i] = i*i
...     x += i
...     return x, d
... 
>>> f( 2 )
(5, {2: 4})
Run Code Online (Sandbox Code Playgroud)

但是当我接下来打电话给f时,我得到:

>>> f(3)
(6, {2: 4, 3: 9})
Run Code Online (Sandbox Code Playgroud)

看起来第二次调用时的关键字参数d不指向空字典,而是指向前一次调用结束时留下的字典.每次通话时,号码x重置为3.

现在我可以解决这个问题,但我希望你的帮助能够理解这一点.我相信关键字参数在函数的本地范围内,并且一旦函数返回就会被删除.(如果我不精确,请原谅并纠正我的术语.)

因此,应删除名称d指向的本地值,并在下一次调用时,如果我不提供关键字参数d,则应将d设置为default {}.但正如您所看到的,d被设置为前一个调用中指向的字典.

到底是怎么回事?

literal {}在封闭范围的防线?

在2.5,2.6和3.1中可以看到此行为.

python dictionary scope keyword-argument

26
推荐指数
1
解决办法
2万
查看次数

只有在尚未存在的情况下才能创建新对象的最快方法(SQLAlchemy)

我正在寻找创建新SQLAlchemy对象的最快方法,只有在数据库中不存在它时.

我现在这样做的方法是首先获取查询的计数以查看它是否存在,如果不存在 - 然后我创建它.例如:

if not User.query.filter(email=user.email).count():
    db.session.add(user)
    db.session.commit()
Run Code Online (Sandbox Code Playgroud)

这是最好的方法吗?会喜欢一些反馈.谢谢!

python database postgresql sqlalchemy flask-sqlalchemy

23
推荐指数
0
解决办法
2万
查看次数

在SQL Server 2005上INSERT WHERE COUNT(*)= 0上违反UNIQUE KEY约束

我从多个进程插入一个SQL数据库.过程有时可能会尝试将重复数据插入表中.我试图以一种处理重复的方式编写查询,但我仍然得到:

System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'UK1_MyTable'. Cannot insert duplicate key in object 'dbo.MyTable'.
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

我的查询看起来像:

INSERT INTO MyTable (FieldA, FieldB, FieldC)
SELECT FieldA='AValue', FieldB='BValue', FieldC='CValue'
WHERE (SELECT COUNT(*) FROM MyTable WHERE FieldA='AValue' AND FieldB='BValue' AND FieldC='CValue' ) = 0
Run Code Online (Sandbox Code Playgroud)

约束'UK1_MyConstraint'表示在MyTable中,3个字段的组合应该是唯一的.

我的问题:

  1. 为什么这不起作用?
  2. 我需要进行哪些修改才能因违反约束而无法出现异常?

请注意,我知道还有其他方法可以解决"INSERT if not exists"的原始问题,例如(摘要):

  • 使用TRY CATCH
  • 如果不存在INSERT(在具有可序列化隔离的事务中)

我应该使用其中一种方法吗?

编辑1个 SQL用于创建表:

CREATE TABLE [dbo].[MyTable](
  [Id] [bigint] IDENTITY(1,1) NOT NULL,
  [FieldA] [bigint] NOT NULL,
  [FieldB] [int] NOT NULL,
  [FieldC] [char](3) NULL,
  [FieldD] [float] …
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2005

21
推荐指数
2
解决办法
3万
查看次数

涉及子选择和外键的 Postgres 竞争条件

我们有 2 个表定义如下

CREATE TABLE foo (
  id BIGSERIAL PRIMARY KEY,
  name TEXT NOT NULL UNIQUE
);

CREATE TABLE bar (
  foo_id BIGINT UNIQUE,
  foo_name TEXT NOT NULL UNIQUE REFERENCES foo (name)
);

Run Code Online (Sandbox Code Playgroud)

我注意到在同时执行以下两个查询时

INSERT INTO foo (name) VALUES ('BAZ')
Run Code Online (Sandbox Code Playgroud)
INSERT INTO bar (foo_name, foo_id) VALUES ('BAZ', (SELECT id FROM foo WHERE name = 'BAZ'))
Run Code Online (Sandbox Code Playgroud)

在某些情况下,最终可能会在barwhere foo_idis 中插入一行NULL。这两个查询由两个完全不同的进程在不同的事务中执行。

这怎么可能?我希望第二条语句要么由于外键违规而失败(如果记录foo不存在),要么以非空值foo_id(如果是)成功。

是什么导致了这种竞争条件?是由于子选择,还是由于检查外键约束的时间?

我们使用隔离级别“已提交读”和 postgres 10.3 版。

编辑

我认为这个问题并不清楚是什么让我感到困惑。问题是关于在执行单个语句期间如何以及为什么观察到数据库的 2 个不同状态。subselect 观察到 foo 中的记录不存在,而 …

sql postgresql concurrency foreign-keys subquery

13
推荐指数
1
解决办法
418
查看次数

SQLAlchemy:检查表中是否已存在对象

我有一个类,Itemid是一个主键并自动生成.现在我从其他外部源读取数据,创建一个Item对象,并需要检查我的items表中是否已存在此对象.我该怎么做?

python sqlalchemy python-3.x

12
推荐指数
2
解决办法
1万
查看次数

使用SQLAlchemy和sqlite嵌套事务

我正在使用SQLAlchemy(和Elixir)用SQLite作为数据库后端在Python中编写应用程序.我使用代码启动一个新的事务session.begin_transaction(),但是当我调用时,session.rollback()我收到以下错误:

sqlalchemy.exceptions.OperationalError: (OperationalError) no such savepoint: sa_savepoint_1 u'ROLLBACK TO SAVEPOINT sa_savepoint_1' []
Run Code Online (Sandbox Code Playgroud)

我也收到类似的错误session.commit().据我所知,sqlite支持SAVEPOINTS(http://www.sqlite.org/lang_savepoint.html).

如何使嵌套事务生效?

python sqlite sqlalchemy python-elixir

5
推荐指数
2
解决办法
3223
查看次数

SqlAlchemy:使用“获取或创建”模式锁定表

我正在使用类似于此问题的答案的 get_or_create 模式:

SQLAlchemy 是否有相当于 Django 的 get_or_create 的功能?

但是我在另一个线程在第一个线程的“选择”和“插入”之间创建实例(具有相同的 pk)时遇到问题。

get_or_create 函数是否应该锁定两个查询的表?使用 SqlAlchemy 实现锁定的最佳方法是什么?

我正在使用 postgresql:http ://www.postgresql.org/docs/current/static/sql-lock.html

我能看到的唯一 sqlalchemy 锁定功能是“ for update ”,这似乎不是正确的锁定类型?

postgresql locking sqlalchemy

5
推荐指数
1
解决办法
4448
查看次数

SQLAlchemy可以添加新记录并自动化表之间的关系而无需手动检查PK唯一性吗?

我是SQLAlchemy的新手,并阅读了基本文档.我目前正在关注Mike Driscoll的MediaLocker教程并根据自己的目的修改/扩展它.

我有三张桌子(贷款,人,卡).贷款卡和贷款人都是一对多的关系,并建模如下:

from sqlalchemy import Table, Column, DateTime, Integer, ForeignKey, Unicode
from sqlalchemy.orm import backref, relation
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("sqlite:///cardsys.db", echo=True)
DeclarativeBase = declarative_base(engine)
metadata = DeclarativeBase.metadata

class Loan(DeclarativeBase):
    """
    Loan model
    """

    __tablename__ = "loans"

    id = Column(Integer, primary_key=True)
    card_id = Column(Unicode, ForeignKey("cards.id"))
    person_id = Column(Unicode, ForeignKey("people.id"))
    date_issued = Column(DateTime)
    date_due = Column(DateTime)
    date_returned = Column(DateTime)
    issue_reason = Column(Unicode(50))
    person = relation("Person", backref="loans", cascade_backrefs=False)
    card = relation("Card", backref="loans", cascade_backrefs=False) …
Run Code Online (Sandbox Code Playgroud)

python sqlalchemy primary-key relational-database

5
推荐指数
1
解决办法
3825
查看次数

插入对象的最快方法(如果SQLAlchemy不存在)

所以我对SQLAlchemy很新.

我有一个模型显示表中有大约10,000行.这是班级:

class Showing(Base):
    __tablename__   = "showings"

    id              = Column(Integer, primary_key=True)
    time            = Column(DateTime)
    link            = Column(String)
    film_id         = Column(Integer, ForeignKey('films.id'))
    cinema_id       = Column(Integer, ForeignKey('cinemas.id'))

    def __eq__(self, other):
        if self.time == other.time and self.cinema == other.cinema and self.film == other.film:
            return True
        else:
            return False
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我一些关于插入新表现的最快方法的指导,如果它还不存在的话.我觉得它稍微复杂一点,因为如果时间,电影和电影在表演中是独一无二的,那么表演才是唯一的.

我目前有这个代码:

def AddShowings(self, showing_times, cinema, film):
    all_showings = self.session.query(Showing).options(joinedload(Showing.cinema), joinedload(Showing.film)).all()
    for showing_time in showing_times:
        tmp_showing = Showing(time=showing_time[0], film=film, cinema=cinema, link=showing_time[1])
        if tmp_showing not in all_showings:
            self.session.add(tmp_showing)
            self.session.commit()
            all_showings.append(tmp_showing)
Run Code Online (Sandbox Code Playgroud)

哪个有效,但似乎很慢.任何帮助深表感谢.

python mysql sqlalchemy

4
推荐指数
1
解决办法
5204
查看次数

在插入 Python 之前进行 SQLAlchemy 检查

我有一个关于如何检查条目是否已经在数据库表中的更合适/更有效的方法的问题。

假设我有一个Foo用单个属性调用的表,Name它也是unique

如果已经存在具有此类名称的条目,在插入之前检查的更好方法是什么?我可以想到两种选择:

from sqlalchemy import MetaData, Table, Column, String, \
create_engine
from sqlalchemy.orm import mapper, relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import IntegrityError

Base = declarative_base()

class Foo(Base):
    __tablename__ = "foo"

    name = Column(String(), primary_key=True)

    @staticmethod
    def silent_insert1(name):
            if not session.query(Foo).filter(Foo.name == name).first():
                    foo = Foo()
                    foo.name = name
                    session.add(foo)
                    session.commit()
            else:
                    print("already exists 1")

    @staticmethod
    def silent_insert2(name):
            try:
                    foo = Foo()
                    foo.name = name
                    session.add(foo)
                    session.commit()
            except(IntegrityError):
                    print("already exists 2") …
Run Code Online (Sandbox Code Playgroud)

python sqlalchemy exception race-condition

4
推荐指数
1
解决办法
2103
查看次数

使用sqlalchemy检查行和返回id的存在是否缓慢

所有,

我正在读一个csv文件并使用sqlalchemy将数据添加到MySQL数据库.其中一个表是地址表,它只能保存唯一的地址.这些地址与另一个具有地址id的外键字段的"语句"表之间存在关系.

因此,对于我的数据文件中的每一行,我创建一个新的语句obj,然后获取相关地址的id.如果地址已存在,则返回该id.否则,我创建一个新的地址obj并返回该id.这是使用下面的代码完成的,改编自这个SO问题.

def get_or_create(self, model, rec):
    instance = self.session.query(model).filter_by(**dict(filter(lambda (x,y): x in model.__dict__.keys(), rec.iteritems()))).first()
    if instance:
        return instance
    else:
        instance = model(rec)
        return instance
Run Code Online (Sandbox Code Playgroud)

我正在使用GUID作为我的id字段,它是地址表的主键的一部分:

class address(Base):
    __tablename__ = 'address'
    id = id_column()
    name               = Column(String(75), primary_key=True)
    Address_Line_One   = Column(String(50), primary_key=True)
    Address_Line_Two   = Column(String(50), primary_key=True)
    Address_Line_Three = Column(String(50), primary_key=True)
    Address_Line_Four  = Column(String(50), primary_key=True)
Run Code Online (Sandbox Code Playgroud)

id_column()来自这里,虽然它已被转换为CHAR(32)由于限制别处.最后,这里有一个片段:

currStatement   = statements(rec, id=currGUID)
currStatement.address = self.get_or_create(address, rec)
Run Code Online (Sandbox Code Playgroud)

这一切都很好,除非它很慢.对于在一个事务中插入的~65,000个语句,我看到干净测试DB上的1.5小时插入时间.实时观察插入显示它快速达到~10,000行,然后插入速度开始下降.

我该怎么做才能加快插入时间?

编辑:

经过进一步测试,我发现插入时间慢是因为每个对象都是单独插入的.所以,我有~65,000行,每行都有几个sqlalchemy对象,单独插入.使用sqlalchemy 0.7,我如何批量插入对象?

mysql bulkinsert sqlalchemy insert-update

3
推荐指数
1
解决办法
1881
查看次数