SQL Server 系统时间日期精度

问题描述 投票:0回答:1

我有一个系统时态 SQL Server 表,为行开始日期生成的日期似乎不正确。

我有一个 Flask + SQLAlchemy REST API 将数据插入到临时表中。我的表中有两个日期 - 第一个是应用程序生成的;第二个是应用程序生成的。另一个是将记录写入数据库时创建的行开始日期。即使我在两个步骤之间放置

time.sleep(1)
,应用程序生成的日期也会晚于系统临时日期。

为什么应用程序生成的日期并不总是早于系统生成的日期?

下面是一个例子。

型号

class TestModel(db.Model):
    __tablename__ = "testtbl"

    id = db.Column(db.Integer, primary_key=True)
    asofdts = db.Column(DATETIME2, nullable=False)

    @classmethod
    def add_system_versioning(
        cls,
        row_eff_dts="row_eff_dts",
        row_exp_dts="row_exp_dts",
        *args,
        **kwargs,
    ):
        """
        Enable system versioning on this table. First, add the row eff/exp dates. Then, add a history table.
        """
        HISTORY_TABLE_NAME = f"dbo.{cls.__tablename__}_history"

        sql = f"""
        ALTER TABLE {cls.__tablename__}
        ADD 
            {row_eff_dts} DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT GETUTCDATE(),
            {row_exp_dts} DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT CONVERT(DATETIME2, '9999-12-31 00:00:00.0000000'),
        PERIOD FOR SYSTEM_TIME ({row_eff_dts}, {row_exp_dts})
        """
        try:
            db.session.execute(text(sql))
            db.session.commit()
        except Exception:
            db.session.rollback()

        sql = f"""
        ALTER TABLE {cls.__tablename__}
        SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE={HISTORY_TABLE_NAME}))
        """
        try:
            db.session.execute(text(sql))
            db.session.commit()
        except Exception:
            db.session.rollback()

API资源

class TestResource(Resource):
    def get(self, *args, **kwargs):
        # setup the table
        db.create_all()
        TestModel.add_system_versioning()
        return {"hello": "world"}

    def post(self, *args, **kwargs):
        # get the current UTC datetime from the database (which is what the row_eff_dts should use too!)
        asofdts = db.session.execute(
            text("SELECT CAST(GETUTCDATE() AS DATETIME2)")
        ).scalar()
        time.sleep(1)
        # create a new row
        obj = TestModel(asofdts=asofdts)
        db.session.add(obj)
        db.session.commit()

        return {"hello": "world"}

结果

请注意,

row_eff_dts
位于
asofdts
列之前 5 秒或更长时间。

一切都在本地运行。 SQL Server 也在本地的 Docker 容器中运行。

sql-server t-sql flask sqlalchemy temporal-tables
1个回答
0
投票

多亏了 Charlieface,我找到了解决方案。原始代码在单个事务中运行,行开始日期是事务的开始。如果我修改代码以在单独的事务中获取

asofdts
,那么一切都会按预期进行。

def post(self, *args, **kwargs):
    # get the current UTC datetime from the database (which is what the row_eff_dts should use too!)
    with db.session.begin():
        asofdts, transaction_id = db.session.execute(
            text(
                "SELECT CAST(GETUTCDATE() AS DATETIME2) AS asofdts, CURRENT_TRANSACTION_ID() AS transaction_id"
            )
        ).first()
        print(transaction_id)


    _, transaction_id = db.session.execute(
        text(
            "SELECT CAST(GETUTCDATE() AS DATETIME2) AS asofdts, CURRENT_TRANSACTION_ID() AS transaction_id"
        )
    ).first()
    print(transaction_id) # this is a new transaction
    # create a new row
    obj = TestModel(asofdts=asofdts)
    db.session.add(obj)
    db.session.commit()

    return {"hello": "world"}

新结果:

© www.soinside.com 2019 - 2024. All rights reserved.