In SQL, if you want to remove a column from a table, you need to use the ALTER TABLE
statement with the DROP COLUMN
clause.
That removes the column and all its data.
Syntax
The syntax goes like this:
ALTER TABLE table_name
DROP COLUMN column_name;
Some RDBMSs accept an optional IF EXISTS
argument which means that it won’t return an error if the column doesn’t exist.
Some RDBMSs also accept optional CASCADE
and RESTRICT
arguments, which specify what to do if the column has any dependencies. See below for more on this.
Example
Here’s an example to demonstrate.
ALTER TABLE Products
DROP COLUMN ProductDescription;
This removes the ProductDescription
column from the Products
table.
The IF EXISTS
Argument
Depending on your RDBMS, you may be able to use the IF EXISTS
argument, which conditionally drops the column only if it already exists.
The benefit of doing this is that you won’t get an error if the column doesn’t exist.
Example:
ALTER TABLE Products
DROP COLUMN IF EXISTS ProductDescription;
Restrict the Change
Depending on your RDBMS, you may be able to use the CASCADE
and RESTRICT
arguments to specify what to do if the column has any dependencies, such as foreign keys or views.
RESTRICT
is typically the default behavior, so if you don’t specify any of these arguments, the DBMS will refuse to drop the column if there are any dependent objects.
Example:
ALTER TABLE Products
DROP COLUMN ProductDescription RESTRICT;
When using the above statement, if the column has any dependencies, the drop operation will fail, and you’ll get an error.
Here’s the error I get in PostgreSQL when trying to drop a table that’s referenced by a view:
cannot drop column productdescription of table products because other objects depend on it
Cascade the Change
Using the CASCADE
option will cause any dependent objects to be dropped.
Here’s what happens if I change the previous example to CASCADE
:
ALTER TABLE Products
DROP COLUMN ProductDescription CASCADE;
Result:
NOTICE: drop cascades to view vproducts Commands completed successfully
In this case, the column was dropped and I got a message explaining that the view called vproducts
was also dropped.
CASCADE
and RESTRICT
are supported in PostgreSQL, but not in SQL Server or MySQL. Both keywords are able to be used in MariaDB but they don’t have any effect.
Oracle accepts a CASCADE CONSTRAINTS
clause which drops all foreign key constraints that refer to the primary and unique keys defined on the dropped columns as well as all multicolumn constraints defined on the dropped columns.
Drop Multiple Columns
Some RDBMs allow you to drop multiple columns within a single ALTER TABLE
statement. The syntax varies between RDBMS.
In SQL Server, you can simply list each column, separated by a comma:
ALTER TABLE t1
DROP COLUMN c1, c2;
In other RDBMSs (such as MySQL and PostgreSQL), you would need to rewrite DROP COLUMN
for each column:
ALTER TABLE t1
DROP COLUMN c1, DROP COLUMN c2;
Note that this syntax is an extension to SQL, and it doesn’t conform to the SQL standard of only having one DROP
clause per ALTER TABLE
statement.
Drop the Last Column
Some RDBMs allow you to drop the last column in the table, therefore leaving an empty table with no columns. This is an extension of the SQL standard (which doesn’t allow zero-column tables).
For example, in PostgreSQL, I used the following statement to drop the last remaining column in the table
ALTER TABLE t1
DROP COLUMN c3;
Result:
Commands completed successfully
But in SQL Server, if I do the same:
ALTER TABLE t1
DROP COLUMN c1, c2, c3;
Result:
Msg 4923, Level 16, State 1, Line 1 ALTER TABLE DROP COLUMN failed because 'c3' is the only data column in table 't1'. A table must have at least one data column.
Note that despite the wording of this error message, c3 wasn’t the only remaining column. There were actually three columns. However, c3 would have been the last one remaining if the other two had been dropped. In this case, none of the three columns were actually dropped.
Either way, even if I did drop the other two, SQL Server would refuse to drop the last one.
MySQL also refuses to drop the last column in a table.
If your intention is to drop the table, use DROP TABLE
.
Restrictions by RDBMS
Although the basic DROP COLUMN
syntax is pretty similar across most of the major RDBMSs, each RDBMS tends to have its own restrictions for when a column will or won’t be dropped.
Here are some of the restrictions from some of the major RDBMSs.
SQL Server
A column can’t be dropped when it’s:
- Used in an index, whether as a key column or as an
INCLUDE
- Used in a
CHECK
,FOREIGN KEY
,UNIQUE
, orPRIMARY KEY
constraint. - Associated with a default that’s defined with the
DEFAULT
keyword, or bound to a default object. - Bound to a rule.
Source for SQL Server: https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql
MySQL
If columns are dropped from a table, the columns are also removed from any index of which they are a part. If all columns that make up an index are dropped, the index is dropped as well.
Source for MySQL: https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
PostgreSQL
Indexes and table constraints involving the column will be automatically dropped as well.
Multivariate statistics referencing the dropped column will also be removed if the removal of the column would cause the statistics to contain data for only a single column.
You will need to use CASCADE
if anything outside the table depends on the column, for example, foreign keys or views.
Source for PostgreSQL: https://www.postgresql.org/docs/current/sql-altertable.html
SQLite
SQLite doesn’t support the DROP COLUMN
syntax. You can’t drop a column in SQLite.
If you need to drop a column in SQLite, it’s recommended that you follow the 12 step process recommended in the SQLite documentation.
Source for SQLite: https://sqlite.org/lang_altertable.html#otheralter
MariaDB
If the column is part of any index, the column will be dropped from them, except if you add a new column with identical name at the same time. The index will be dropped if all columns from the index were dropped. If the column was used in a view or trigger, you will get an error next time the view or trigger is accessed.
From MariaDB 10.2.8, dropping a column that is part of a multi-column UNIQUE
constraint is not permitted.
MariaDB accepts RESTRICT
and CASCADE
in order to make porting from other database systems easier, but in MariaDB, they do nothing.
MariaDB 10.4.0 supports instant DROP COLUMN
. DROP COLUMN
of an indexed column would imply DROP INDEX
(and in the case of a non-UNIQUE
multi-column index, possibly ADD INDEX
). These will not be allowed with ALGORITHM=INSTANT
, but unlike before, they can be allowed with ALGORITHM=NOCOPY
.
Source for MariaDB: https://mariadb.com/kb/en/alter-table/#drop-column