diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c
index 1ec153815bd2f6d22b2897950d5ab20924406273..705caf1ca7c9d8d11a6ab1ca4056119353315353 100644
--- a/extra/mkkeywordhash.c
+++ b/extra/mkkeywordhash.c
@@ -281,6 +281,7 @@ static Keyword aKeywordTable[] = {
   { "VARCHAR",                "TK_ID",          RESERVED,         true  },
   { "WHENEVER",               "TK_STANDARD",    RESERVED,         true  },
   { "WHILE",                  "TK_STANDARD",    RESERVED,         true  },
+  { "TRUNCATE",               "TK_TRUNCATE",    ALWAYS,           true  },
 };
 
 /* Number of keywords */
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 06811778f26979e1514137588d9cb99fb8432cb8..c9d237fdf6d78ef3c5d7380715990ab52643ba68 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -71,6 +71,50 @@ sql_materialize_view(struct Parse *parse, const char *name, struct Expr *where,
 	sql_select_delete(db, select);
 }
 
+void
+sql_table_truncate(struct Parse *parse, struct SrcList *tab_list)
+{
+	assert(tab_list->nSrc == 1);
+
+	struct Vdbe *v = sqlite3GetVdbe(parse);
+	if (v == NULL)
+		goto cleanup;
+
+	const char *tab_name = tab_list->a->zName;
+	uint32_t space_id = box_space_id_by_name(tab_name, strlen(tab_name));
+	if (space_id == BOX_ID_NIL) {
+		diag_set(ClientError, ER_NO_SUCH_SPACE, tab_name);
+		goto tarantool_error;
+	}
+	struct space *space = space_cache_find(space_id);
+	assert(space != NULL);
+
+	struct Table *table = sqlite3LocateTable(parse, LOCATE_NOERR, tab_name);
+	if (table != NULL && sqlite3FkReferences(table) != NULL) {
+		const char *err_msg =
+			tt_sprintf("can not truncate space '%s' because other "
+				   "objects depend on it", space->def->name);
+		diag_set(ClientError, ER_SQL, err_msg);
+		goto tarantool_error;
+	}
+	if (space->def->opts.is_view) {
+		const char *err_msg =
+			tt_sprintf("can not truncate space '%s' because it is "
+				   "a view", space->def->name);
+		diag_set(ClientError, ER_SQL, err_msg);
+		goto tarantool_error;
+	}
+	sqlite3VdbeAddOp2(v, OP_Clear, space->def->id, true);
+cleanup:
+	sqlite3SrcListDelete(parse->db, tab_list);
+	return;
+
+tarantool_error:
+	parse->rc = SQL_TARANTOOL_ERROR;
+	parse->nErr++;
+	goto cleanup;
+}
+
 void
 sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 		      struct Expr *where)
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 71518e0a0ec1f72ce0d53e08f06066cbf3e74e30..0e50d21fb21efd28bc319e421b7554f48c768483 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -733,6 +733,12 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
   sql_table_delete_from(pParse,X,W);
 }
 
+/////////////////////////// The TRUNCATE statement /////////////////////////////
+//
+cmd ::= TRUNCATE TABLE fullname(X). {
+  sql_table_truncate(pParse, X);
+}
+
 %type where_opt {Expr*}
 %destructor where_opt {sql_expr_delete(pParse->db, $$, false);}
 
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 8cc2288a391eda1dcedf98ad31338918a050010a..5ca91b2e0c2517e7b03ff46c1822dee447d0b77c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -3719,6 +3719,15 @@ void
 sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 		      struct Expr *where);
 
+/**
+ * Generate a code for TRUNCATE TABLE statement.
+ *
+ * @param parse Parsing context.
+ * @param tab_list List of single table to truncate.
+ */
+void
+sql_table_truncate(struct Parse *parse, struct SrcList *tab_list);
+
 void sqlite3Update(Parse *, SrcList *, ExprList *, Expr *,
 		   enum on_conflict_action);
 WhereInfo *sqlite3WhereBegin(Parse *, SrcList *, Expr *, ExprList *, ExprList *,
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 1a75f77ebc2894075c3d3f978c5eefff745e3f3f..dc22c26933860a8599da24870ea67f47e71e3998 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -39,6 +39,7 @@
  * in this file for details.  If in doubt, do not deviate from existing
  * commenting and indentation practices when changing or adding code.
  */
+#include "box/box.h"
 #include "box/txn.h"
 #include "box/session.h"
 #include "sqliteInt.h"
@@ -4562,8 +4563,9 @@ case OP_IdxGE:  {       /* jump */
 	break;
 }
 
-/* Opcode: Clear P1 * * * *
+/* Opcode: Clear P1 P2 * * *
  * Synopsis: space id = P1
+ * If P2 is not 0, use Truncate semantics.
  *
  * Delete all contents of the space, which space id is given
  * in P1 argument. It is worth mentioning, that clearing routine
@@ -4575,7 +4577,13 @@ case OP_Clear: {
 	uint32_t space_id = pOp->p1;
 	struct space *space = space_by_id(space_id);
 	assert(space != NULL);
-	rc = tarantoolSqlite3ClearTable(space);
+	rc = 0;
+	if (pOp->p2 > 0) {
+		if (box_truncate(space_id) != 0)
+			rc = SQL_TARANTOOL_ERROR;
+	} else {
+		rc = tarantoolSqlite3ClearTable(space);
+	}
 	if (rc) goto abort_due_to_error;
 	break;
 }
diff --git a/test/sql/delete.result b/test/sql/delete.result
index c33079cd7187dd33a213b08452af202901c3c607..52f9969c1c34510a321b4cd324ac11051e4a6d24 100644
--- a/test/sql/delete.result
+++ b/test/sql/delete.result
@@ -59,3 +59,79 @@ box.sql.execute("INSERT INTO t2 VALUES (0);")
 box.sql.execute("DROP TABLE t2;")
 ---
 ...
+--
+-- gh-2201: TRUNCATE TABLE operation.
+--
+-- can't truncate system table.
+box.sql.execute("TRUNCATE TABLE \"_sql_stat1\";")
+---
+- error: Can't truncate a system space, space '_sql_stat1'
+...
+box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b STR);")
+---
+...
+box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
+---
+...
+box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
+---
+...
+-- Can't truncate in transaction.
+box.sql.execute("START TRANSACTION")
+---
+...
+box.sql.execute("TRUNCATE TABLE t1;")
+---
+- error: DDL does not support multi-statement transactions
+...
+box.sql.execute("ROLLBACK")
+---
+...
+-- Can't truncate view.
+box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+---
+...
+box.sql.execute("TRUNCATE TABLE v1;")
+---
+- error: 'SQL error: can not truncate space ''V1'' because it is a view'
+...
+-- Can't truncate table with FK.
+box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
+---
+...
+box.sql.execute("TRUNCATE TABLE t1;")
+---
+- error: 'SQL error: can not truncate space ''T1'' because other objects depend on
+    it'
+...
+-- Table triggers should be ignored.
+box.sql.execute("DROP TABLE t2;")
+---
+...
+box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
+---
+...
+box.sql.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
+---
+...
+box.sql.execute("TRUNCATE TABLE t1;")
+---
+...
+box.sql.execute("SELECT * FROM t1;")
+---
+- []
+...
+box.sql.execute("SELECT * FROM t2;")
+---
+- []
+...
+-- Cleanup.
+box.sql.execute("DROP VIEW v1");
+---
+...
+box.sql.execute("DROP TABLE t1;")
+---
+...
+box.sql.execute("DROP TABLE t2;")
+---
+...
diff --git a/test/sql/delete.test.lua b/test/sql/delete.test.lua
index 1721989604523b55e45b7c58b0d99bd987147dbf..0477d227c84efa6ce4d6b477e97c7c0a68ccf63a 100644
--- a/test/sql/delete.test.lua
+++ b/test/sql/delete.test.lua
@@ -37,3 +37,41 @@ box.sql.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END
 box.sql.execute("INSERT INTO t2 VALUES (0);")
 
 box.sql.execute("DROP TABLE t2;")
+
+
+--
+-- gh-2201: TRUNCATE TABLE operation.
+--
+
+-- can't truncate system table.
+box.sql.execute("TRUNCATE TABLE \"_sql_stat1\";")
+
+box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b STR);")
+box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
+box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
+
+-- Can't truncate in transaction.
+box.sql.execute("START TRANSACTION")
+box.sql.execute("TRUNCATE TABLE t1;")
+box.sql.execute("ROLLBACK")
+
+-- Can't truncate view.
+box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.sql.execute("TRUNCATE TABLE v1;")
+
+-- Can't truncate table with FK.
+box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
+box.sql.execute("TRUNCATE TABLE t1;")
+
+-- Table triggers should be ignored.
+box.sql.execute("DROP TABLE t2;")
+box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
+box.sql.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
+box.sql.execute("TRUNCATE TABLE t1;")
+box.sql.execute("SELECT * FROM t1;")
+box.sql.execute("SELECT * FROM t2;")
+
+-- Cleanup.
+box.sql.execute("DROP VIEW v1");
+box.sql.execute("DROP TABLE t1;")
+box.sql.execute("DROP TABLE t2;")