diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php
index 1a1408876f1618d5cea16475b54ea369351cd4a1..1d97faf77cc2c4d50da953ae479a730179a2a14f 100644
--- a/lib/private/db/querybuilder/querybuilder.php
+++ b/lib/private/db/querybuilder/querybuilder.php
@@ -37,6 +37,9 @@ class QueryBuilder implements IQueryBuilder {
 	/** @var QuoteHelper */
 	private $helper;
 
+	/** @var bool */
+	private $automaticTablePrefix = true;
+
 	/**
 	 * Initializes a new QueryBuilder.
 	 *
@@ -48,6 +51,17 @@ class QueryBuilder implements IQueryBuilder {
 		$this->helper = new QuoteHelper();
 	}
 
+	/**
+	 * Enable/disable automatic prefixing of table names with the oc_ prefix
+	 *
+	 * @param bool $enabled If set to true table names will be prefixed with the
+	 * owncloud database prefix automatically.
+	 * @since 8.2.0
+	 */
+	public function automaticTablePrefix($enabled) {
+		$this->automaticTablePrefix = (bool) $enabled;
+	}
+
 	/**
 	 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
 	 * This producer method is intended for convenient inline usage. Example:
@@ -329,7 +343,7 @@ class QueryBuilder implements IQueryBuilder {
 	 */
 	public function delete($delete = null, $alias = null) {
 		$this->queryBuilder->delete(
-			$this->helper->quoteColumnName($delete),
+			$this->getTableName($delete),
 			$alias
 		);
 
@@ -354,7 +368,7 @@ class QueryBuilder implements IQueryBuilder {
 	 */
 	public function update($update = null, $alias = null) {
 		$this->queryBuilder->update(
-			$this->helper->quoteColumnName($update),
+			$this->getTableName($update),
 			$alias
 		);
 
@@ -382,7 +396,7 @@ class QueryBuilder implements IQueryBuilder {
 	 */
 	public function insert($insert = null) {
 		$this->queryBuilder->insert(
-			$this->helper->quoteColumnName($insert)
+			$this->getTableName($insert)
 		);
 
 		return $this;
@@ -405,7 +419,7 @@ class QueryBuilder implements IQueryBuilder {
 	 */
 	public function from($from, $alias = null) {
 		$this->queryBuilder->from(
-			$this->helper->quoteColumnName($from),
+			$this->getTableName($from),
 			$alias
 		);
 
@@ -432,7 +446,7 @@ class QueryBuilder implements IQueryBuilder {
 	public function join($fromAlias, $join, $alias, $condition = null) {
 		$this->queryBuilder->join(
 			$fromAlias,
-			$this->helper->quoteColumnName($join),
+			$this->getTableName($join),
 			$alias,
 			$condition
 		);
@@ -460,7 +474,7 @@ class QueryBuilder implements IQueryBuilder {
 	public function innerJoin($fromAlias, $join, $alias, $condition = null) {
 		$this->queryBuilder->innerJoin(
 			$fromAlias,
-			$this->helper->quoteColumnName($join),
+			$this->getTableName($join),
 			$alias,
 			$condition
 		);
@@ -488,7 +502,7 @@ class QueryBuilder implements IQueryBuilder {
 	public function leftJoin($fromAlias, $join, $alias, $condition = null) {
 		$this->queryBuilder->leftJoin(
 			$fromAlias,
-			$this->helper->quoteColumnName($join),
+			$this->getTableName($join),
 			$alias,
 			$condition
 		);
@@ -516,7 +530,7 @@ class QueryBuilder implements IQueryBuilder {
 	public function rightJoin($fromAlias, $join, $alias, $condition = null) {
 		$this->queryBuilder->rightJoin(
 			$fromAlias,
-			$this->helper->quoteColumnName($join),
+			$this->getTableName($join),
 			$alias,
 			$condition
 		);
@@ -984,4 +998,16 @@ class QueryBuilder implements IQueryBuilder {
 	public function createFunction($call) {
 		return new QueryFunction($call);
 	}
+
+	/**
+	 * @param string $table
+	 * @return string
+	 */
+	private function getTableName($table) {
+		if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) {
+			return $this->helper->quoteColumnName($table);
+		}
+
+		return $this->helper->quoteColumnName('*PREFIX*' . $table);
+	}
 }
diff --git a/lib/public/db/querybuilder/iquerybuilder.php b/lib/public/db/querybuilder/iquerybuilder.php
index 09d5d199bef7435ccfff10ab5344c0dfa09d39e4..3fc07af1a471bad034a0bf12b6690a363843d480 100644
--- a/lib/public/db/querybuilder/iquerybuilder.php
+++ b/lib/public/db/querybuilder/iquerybuilder.php
@@ -26,6 +26,15 @@ namespace OCP\DB\QueryBuilder;
  * @since 8.2.0
  */
 interface IQueryBuilder {
+	/**
+	 * Enable/disable automatic prefixing of table names with the oc_ prefix
+	 *
+	 * @param bool $enabled If set to true table names will be prefixed with the
+	 * owncloud database prefix automatically.
+	 * @since 8.2.0
+	 */
+	public function automaticTablePrefix($enabled);
+
 	/**
 	 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
 	 * This producer method is intended for convenient inline usage. Example:
diff --git a/tests/lib/db/querybuilder/querybuildertest.php b/tests/lib/db/querybuilder/querybuildertest.php
index 02e516b7386667ac0b81df6c8da16d5b70692cd3..75e62ba944ef1c4807578b272019a7e8a7d09d53 100644
--- a/tests/lib/db/querybuilder/querybuildertest.php
+++ b/tests/lib/db/querybuilder/querybuildertest.php
@@ -253,8 +253,8 @@ class QueryBuilderTest extends \Test\TestCase {
 
 	public function dataDelete() {
 		return [
-			['data', null, ['table' => '`data`', 'alias' => null], '`data`'],
-			['data', 't', ['table' => '`data`', 'alias' => 't'], '`data` t'],
+			['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
+			['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
 		];
 	}
 
@@ -282,8 +282,8 @@ class QueryBuilderTest extends \Test\TestCase {
 
 	public function dataUpdate() {
 		return [
-			['data', null, ['table' => '`data`', 'alias' => null], '`data`'],
-			['data', 't', ['table' => '`data`', 'alias' => 't'], '`data` t'],
+			['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
+			['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
 		];
 	}
 
@@ -311,7 +311,7 @@ class QueryBuilderTest extends \Test\TestCase {
 
 	public function dataInsert() {
 		return [
-			['data', ['table' => '`data`'], '`data`'],
+			['data', ['table' => '`*PREFIX*data`'], '`*PREFIX*data`'],
 		];
 	}
 
@@ -338,16 +338,16 @@ class QueryBuilderTest extends \Test\TestCase {
 
 	public function dataFrom() {
 		return [
-			['data', null, null, null, [['table' => '`data`', 'alias' => null]], '`data`'],
-			['data', 't', null, null, [['table' => '`data`', 'alias' => 't']], '`data` t'],
+			['data', null, null, null, [['table' => '`*PREFIX*data`', 'alias' => null]], '`*PREFIX*data`'],
+			['data', 't', null, null, [['table' => '`*PREFIX*data`', 'alias' => 't']], '`*PREFIX*data` t'],
 			['data1', null, 'data2', null, [
-				['table' => '`data1`', 'alias' => null],
-				['table' => '`data2`', 'alias' => null]
-			], '`data1`, `data2`'],
+				['table' => '`*PREFIX*data1`', 'alias' => null],
+				['table' => '`*PREFIX*data2`', 'alias' => null]
+			], '`*PREFIX*data1`, `*PREFIX*data2`'],
 			['data', 't1', 'data', 't2', [
-				['table' => '`data`', 'alias' => 't1'],
-				['table' => '`data`', 'alias' => 't2']
-			], '`data` t1, `data` t2'],
+				['table' => '`*PREFIX*data`', 'alias' => 't1'],
+				['table' => '`*PREFIX*data`', 'alias' => 't2']
+			], '`*PREFIX*data` t1, `*PREFIX*data` t2'],
 		];
 	}
 
@@ -382,18 +382,18 @@ class QueryBuilderTest extends \Test\TestCase {
 		return [
 			[
 				'd1', 'data2', null, null,
-				['d1' => [['joinType' => 'inner', 'joinTable' => '`data2`', 'joinAlias' => null, 'joinCondition' => null]]],
-				'`data1` d1 INNER JOIN `data2`  ON '
+				['d1' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 INNER JOIN `*PREFIX*data2`  ON '
 			],
 			[
 				'd1', 'data2', 'd2', null,
-				['d1' => [['joinType' => 'inner', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
-				'`data1` d1 INNER JOIN `data2` d2 ON '
+				['d1' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 INNER JOIN `*PREFIX*data2` d2 ON '
 			],
 			[
 				'd1', 'data2', 'd2', 'd1.`field1` = d2.`field2`',
-				['d1' => [['joinType' => 'inner', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
-				'`data1` d1 INNER JOIN `data2` d2 ON d1.`field1` = d2.`field2`'
+				['d1' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
+				'`*PREFIX*data1` d1 INNER JOIN `*PREFIX*data2` d2 ON d1.`field1` = d2.`field2`'
 			],
 
 		];
@@ -463,18 +463,18 @@ class QueryBuilderTest extends \Test\TestCase {
 		return [
 			[
 				'd1', 'data2', null, null,
-				['d1' => [['joinType' => 'left', 'joinTable' => '`data2`', 'joinAlias' => null, 'joinCondition' => null]]],
-				'`data1` d1 LEFT JOIN `data2`  ON '
+				['d1' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 LEFT JOIN `*PREFIX*data2`  ON '
 			],
 			[
 				'd1', 'data2', 'd2', null,
-				['d1' => [['joinType' => 'left', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
-				'`data1` d1 LEFT JOIN `data2` d2 ON '
+				['d1' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 LEFT JOIN `*PREFIX*data2` d2 ON '
 			],
 			[
 				'd1', 'data2', 'd2', 'd1.`field1` = d2.`field2`',
-				['d1' => [['joinType' => 'left', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
-				'`data1` d1 LEFT JOIN `data2` d2 ON d1.`field1` = d2.`field2`'
+				['d1' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
+				'`*PREFIX*data1` d1 LEFT JOIN `*PREFIX*data2` d2 ON d1.`field1` = d2.`field2`'
 			],
 		];
 	}
@@ -513,18 +513,18 @@ class QueryBuilderTest extends \Test\TestCase {
 		return [
 			[
 				'd1', 'data2', null, null,
-				['d1' => [['joinType' => 'right', 'joinTable' => '`data2`', 'joinAlias' => null, 'joinCondition' => null]]],
-				'`data1` d1 RIGHT JOIN `data2`  ON '
+				['d1' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 RIGHT JOIN `*PREFIX*data2`  ON '
 			],
 			[
 				'd1', 'data2', 'd2', null,
-				['d1' => [['joinType' => 'right', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
-				'`data1` d1 RIGHT JOIN `data2` d2 ON '
+				['d1' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => null]]],
+				'`*PREFIX*data1` d1 RIGHT JOIN `*PREFIX*data2` d2 ON '
 			],
 			[
 				'd1', 'data2', 'd2', 'd1.`field1` = d2.`field2`',
-				['d1' => [['joinType' => 'right', 'joinTable' => '`data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
-				'`data1` d1 RIGHT JOIN `data2` d2 ON d1.`field1` = d2.`field2`'
+				['d1' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => 'd2', 'joinCondition' => 'd1.`field1` = d2.`field2`']]],
+				'`*PREFIX*data1` d1 RIGHT JOIN `*PREFIX*data2` d2 ON d1.`field1` = d2.`field2`'
 			],
 		];
 	}
@@ -591,7 +591,7 @@ class QueryBuilderTest extends \Test\TestCase {
 		);
 
 		$this->assertSame(
-			'UPDATE `data` SET ' . $expectedQuery,
+			'UPDATE `*PREFIX*data` SET ' . $expectedQuery,
 			$this->queryBuilder->getSQL()
 		);
 	}
@@ -774,7 +774,7 @@ class QueryBuilderTest extends \Test\TestCase {
 		);
 
 		$this->assertSame(
-			'INSERT INTO `data` ' . $expectedQuery,
+			'INSERT INTO `*PREFIX*data` ' . $expectedQuery,
 			$this->queryBuilder->getSQL()
 		);
 	}
@@ -799,7 +799,7 @@ class QueryBuilderTest extends \Test\TestCase {
 		);
 
 		$this->assertSame(
-			'INSERT INTO `data` ' . $expectedQuery,
+			'INSERT INTO `*PREFIX*data` ' . $expectedQuery,
 			$this->queryBuilder->getSQL()
 		);
 	}
@@ -996,4 +996,34 @@ class QueryBuilderTest extends \Test\TestCase {
 			$this->queryBuilder->getSQL()
 		);
 	}
+
+	public function dataGetTableName() {
+		return [
+			['*PREFIX*table', null, '`*PREFIX*table`'],
+			['*PREFIX*table', true, '`*PREFIX*table`'],
+			['*PREFIX*table', false, '`*PREFIX*table`'],
+
+			['table', null, '`*PREFIX*table`'],
+			['table', true, '`*PREFIX*table`'],
+			['table', false, '`table`'],
+		];
+	}
+
+	/**
+	 * @dataProvider dataGetTableName
+	 *
+	 * @param string $tableName
+	 * @param bool $automatic
+	 * @param string $expected
+	 */
+	public function testGetTableName($tableName, $automatic, $expected) {
+		if ($automatic !== null) {
+			$this->queryBuilder->automaticTablePrefix($automatic);
+		}
+
+		$this->assertSame(
+			$expected,
+			$this->invokePrivate($this->queryBuilder, 'getTableName', [$tableName])
+		);
+	}
 }