table_name, column,
'sys.check_constraints')
)
+ drop_fks = kw.pop('mssql_drop_foreign_key', False)
+ if drop_fks:
+ self._exec(
+ _exec_drop_col_fk_constraint(self,
+ table_name, column)
+ )
super(MSSQLImpl, self).drop_column(table_name, column)
def _exec_drop_col_constraint(impl, tname, colname, type_):
where parent_object_id = object_id('%(tname)s')
and col_name(parent_object_id, parent_column_id) = '%(colname)s'
exec('alter table %(tname)s drop constraint ' + @const_name)""" % {
- 'type':type_,
- 'tname':tname,
- 'colname':colname
+ 'type': type_,
+ 'tname': tname,
+ 'colname': colname
+ }
+
+def _exec_drop_col_fk_constraint(impl, tname, colname):
+ return """declare @const_name varchar(256)
+select @const_name = [name] from
+ sys.foreign_keys fk join sys.foreign_key_columns fkc
+ on fk.object_id=fkc.constraint_object_id
+where fkc.parent_object_id = object_id('%(tname)s')
+and col_name(fkc.parent_object_id, fkc.parent_column_id) = '%(colname)s'
+exec('alter table %(tname)s drop constraint ' + @const_name)""" % {
+ 'tname': tname,
+ 'colname': colname
}
+
+
@compiles(AddColumn, 'mssql')
def visit_add_column(element, compiler, **kw):
return "%s %s" % (
SQL-script-compatible
block that selects into a @variable from sys.default_constraints,
then exec's a separate DROP CONSTRAINT for that default.
+ :param mssql_drop_foreign_key: Optional boolean. When ``True``, on
+ Microsoft SQL Server only, first
+ drop a single FOREIGN KEY constraint on the column using a
+ SQL-script-compatible
+ block that selects into a @variable from
+ sys.foreign_keys/sys.foreign_key_columns,
+ then exec's a separate DROP CONSTRAINT for that default. Only
+ works if the column has exactly one FK constraint which refers to
+ it, at the moment.
+
+ .. versionadded:: 0.6.2
"""
.. changelog::
:version: 0.6.2
+ .. change::
+ :tags: feature, mssql
+
+ Added new argument ``mssql_drop_foreign_key`` to
+ :meth:`.Operations.drop_column`. Like ``mssql_drop_default``
+ and ``mssql_drop_check``, will do an inline lookup for a
+ single foreign key which applies to this column, and drop it.
+ For a column with more than one FK, you'd still need to explicitly
+ use :meth:`.Operations.drop_constraint` given the name,
+ even though only MSSQL has this limitation in the first place.
+
.. change::
:tags: bug, mssql
:pullreq: bitbucket:13
"ALTER TABLE t ALTER COLUMN c INTEGER NULL"
)
+ def test_drop_column_w_fk(self):
+ context = op_fixture('mssql')
+ op.drop_column('t1', 'c1', mssql_drop_foreign_key=True)
+ context.assert_contains("exec('alter table t1 drop constraint ' + @const_name)")
+ context.assert_contains("ALTER TABLE t1 DROP COLUMN c1")
+
def test_alter_column_not_nullable_w_existing_type(self):
context = op_fixture('mssql')
op.alter_column("t", "c", nullable=False, existing_type=Integer)