在 Django 中使用 GEOGRAPHY 列更新 SQL Server 表

Posted

技术标签:

【中文标题】在 Django 中使用 GEOGRAPHY 列更新 SQL Server 表【英文标题】:Updating SQL Server table with GEOGRAPHY column in Django 【发布时间】:2015-08-17 22:27:03 【问题描述】:

我有一个 Django 1.8.3 应用程序,我将其作为数据库之一连接到 SQL Server Enterprise 2012。我正在使用django-pyodbc-azure==1.8.3.0,我的连接如下所示:

'sql_server': 
    'ENGINE': 'sql_server.pyodbc',
    'NAME': 'mydb',
    'USER': 'myuser',
    'PASSWORD': 'mypass',
    'HOST': '173.1.1.1',
    'PORT': 1433,
    'OPTIONS': 
        'host_is_server': True,
    
,

我在数据库的表中有一个这样创建的列:

ALTER TABLE mytable ADD geo AS GEOGRAPHY::Point (
    latitude
    ,longitude
    ,4326
    ) persisted;
CREATE spatial INDEX SI_mytable__geo ON mytable (geo)

当尝试通过 Django 管理员更新此表中的任何列时,我收到此错误:

('42000', "[42000] [FreeTDS][SQL Server]UPDATE 失败,因为 以下 SET 选项的设置不正确:'ANSI_NULLS, QUOTED_IDENTIFIER、CONCAT_NULL_YIELDS_NULL、ANSI_WARNINGS、 ANSI_PADDING'。验证 SET 选项是否适用于 计算列上的索引视图和/或索引和/或过滤 索引和/或查询通知和/或 XML 数据类型方法和/或 空间索引操作。 (1934) (SQLExecDirectW)")

我的数据库目前有这样的 SET 选项:

SELECT 
    is_ansi_nulls_on,
    is_ansi_padding_on,
    is_ansi_warnings_on,
    is_arithabort_on,
    is_concat_null_yields_null_on,
    is_numeric_roundabort_on,
    is_quoted_identifier_on
FROM sys.databases

is_ansi_nulls_on    is_ansi_padding_on  is_ansi_warnings_on is_arithabort_on    is_concat_null_yields_null_on   is_numeric_roundabort_on    is_quoted_identifier_on
0   0   0   0   0   0   0

我只在生产中收到此错误,而不是在我的笔记本电脑上运行开发时收到此错误。我了解我需要根据错误和此答案正确更新 SET 选项:https://***.com/a/9235638/1753891

如何告诉 django-pyodbc-azure 在更新此表之前发送正确的 SET 选项?

或者我是否需要更新数据库本身的选项,如果需要,如果我更改这些 SET 选项,是否有任何潜在的陷阱需要注意?

【问题讨论】:

您在开发中使用什么数据库,SQL Server 也是如此?如果 GeoDjango 是任何指标,我认为空间索引不支持 SQL Server over pyodbc:docs.djangoproject.com/en/1.8/ref/contrib/gis/db-api @FlipperPA 是的,SQL Server 2012 也在开发中——这令人困惑。 我认为重要的是会话中的 SET 选项,而不是数据库设置。您是否可以选择在此处使用存储过程(这样您就可以在 proc 的上下文中显式控制 SET 选项)? @BenThul 我确实有能力在服务器上创建存储过程,但是在使用普通 Django 模型和管理员时会发生这种情况。 【参考方案1】:

我最终在模型的保存方法中更改了 SET 选项,这目前有效。

class MyModel(models.Model):
    # Model fields here
    def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None):

        cursor = connections['sql_server'].cursor()
        cursor.execute("""SET ANSI_NULLS ON
        SET QUOTED_IDENTIFIER ON
        SET CONCAT_NULL_YIELDS_NULL ON
        SET ANSI_WARNINGS ON
        SET ANSI_PADDING ON""")
        cursor.close()

        super(MyModel, self).save(force_insert, force_update, using, update_fields)

【讨论】:

以上是关于在 Django 中使用 GEOGRAPHY 列更新 SQL Server 表的主要内容,如果未能解决你的问题,请参考以下文章

使用条件将列更改为单独的数据框

如何将列更改为行

在 F# 中,如何使用 Type Provider 访问 Sql Server Geography 数据类型?

使 Handsontable 自动完成弹出窗口比列更宽

PySpark DataFrame在使用explode之前将字符串的列更改为数组

Oracle:将 VARCHAR2 列更改为 CLOB