Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 防止Django更新MSSQL中的标识列_Sql Server_Django_Django Models_Pyodbc_Django Pyodbc - Fatal编程技术网

Sql server 防止Django更新MSSQL中的标识列

Sql server 防止Django更新MSSQL中的标识列,sql-server,django,django-models,pyodbc,django-pyodbc,Sql Server,Django,Django Models,Pyodbc,Django Pyodbc,我正在使用MSSQL中的遗留数据库。我们有一个表,该表有两列导致我出现问题: class Emp(models.Model): empid = models.IntegerField(_("Unique ID"), unique=True, db_column=u'EMPID') ssn = models.CharField(_("Social security number"), max_length=10, primary_key=True, db_column=u'

我正在使用MSSQL中的遗留数据库。我们有一个表,该表有两列导致我出现问题:

class Emp(models.Model):  
    empid = models.IntegerField(_("Unique ID"), unique=True, db_column=u'EMPID')  
    ssn = models.CharField(_("Social security number"), max_length=10, primary_key=True, db_column=u'SSN') # Field name made lowercase.  
因此,该表将ssn列作为主键,django生成的SQL更新代码的相关部分如下:

UPDATE [EMP] SET [EMPID] = 399, 
......... 
WHERE [EMP].[SSN] = 2509882579 
问题在于EMP.EMPID是MSSQL中的一个标识字段,因此每当我试图保存对现有员工的更改时,pyodbc就会抛出此错误:

ProgrammingError: ('42000', "[42000] [Microsoft][SQL Native Client][SQL Server]C
annot update identity column 'EMPID'. (8102) (SQLExecDirectW); [42000] [Microsof
t][SQL Native Client][SQL Server]Statement(s) could not be prepared. (8180)")
将EMP.EMPID作为标识对程序来说并不重要,因此通过创建一个临时列并复制、删除、重命名来删除它似乎是合乎逻辑的事情。这为将老客户转移到Django中创建了一个额外的步骤,因此我的问题是,是否有任何方法可以防止Django在我对该表进行更新时生成“[EMPID]=XXX”代码段

编辑
我把我的模型修补成这样:

def save(self, *args, **kwargs):
    if self.empid:
        self._meta.local_fields = [f for f in self._meta.local_fields if f.name != 'empid']
        super().save(*args, **kwargs)

这是可行的,它利用了Django在Django/db/models/base.py(525)中填充其sql语句的方式。如果有人有更好的方法或者可以解释为什么这是一个糟糕的做法,我很乐意听到

这个问题由来已久,Sindri找到了一个可行的解决方案,但我想提供一个我已经在生产中使用了几年的解决方案,它不需要在
\u meta
中混日子

我必须编写一个web应用程序,该应用程序与包含许多计算字段的现有业务数据库集成。这些字段通常用于计算记录的状态,几乎用于整个应用程序中的每个对象访问,Django必须能够使用它们

这些类型的字段可以通过模型管理器使用
extra(select=…)
将所需字段添加到查询中

ComputedFieldsManager
代码段:


我对django一无所知,所以我可能在这里,但您是否尝试过使用
Autofield
。类似这样的内容
empid=models.AutoField(…
AutoField
必须是模型的主键,对于旧版DB支持,我必须使用SSN字段作为主键,因此很遗憾,这不是一个选项:(我知道这是一个遗留应用程序,但使用SSN作为主键是一个坏主意。虽然不太可能,但您的应用程序仍有可能在某一天收到相同的SSN(当某人死亡时由社会保障管理局回收),并且您的应用程序将“中断”,至少在数据完整性方面。你能将应用程序更改为使用EMPID作为主键吗?@HardCode:这将是最佳做法,但由于所有其他表都使用ssn字段链接到Emp表,这可能会产生比解决问题更多的问题。好的是,我住在冰岛,人口不到350.000,each应用程序实例仅容纳30到3000名员工,因此风险非常小,尽管存在:)因此,EMPID列是一个标识列,但不是主键?它是否在任何约束中引用或在任何报告中使用?感谢您的输入!ComputedFieldsManager看起来不错,但我担心它不会解决我的问题,因为这意味着整个代码库都会发生变化。抛开它不谈,我真的希望来到这里的人会喜欢它你的回答而不是我的回答:)
class Emp(models.Model):
    ssn = models.CharField(_("Social security number"), max_length=10, primary_key=True, db_column=u'SSN') # Field name made lowercase.

    objects = ComputedFieldsManager(computed_fields=['empid'])


# the empid is added on to the model instance
Emp.objects.all()[0].empid

# you can also search on the computed field
Emp.objects.all().computed_field_in('empid', [1234])