diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py
index 51370ef2acba..251a670bafd4 100644
--- a/django/db/backends/base/operations.py
+++ b/django/db/backends/base/operations.py
@@ -176,7 +176,7 @@ def distinct_sql(self, fields, params):
         else:
             return ['DISTINCT'], []
 
-    def fetch_returned_insert_columns(self, cursor):
+    def fetch_returned_insert_columns(self, cursor, return_params):
         """
         Given a cursor object that has just performed an INSERT...RETURNING
         statement into a table, return the newly created data.
diff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py
index 73a6e8668648..4b3d26d74b1a 100644
--- a/django/db/backends/oracle/features.py
+++ b/django/db/backends/oracle/features.py
@@ -10,6 +10,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     has_select_for_update_of = True
     select_for_update_of_column = True
     can_return_columns_from_insert = True
+    can_return_multiple_columns_from_insert = True
     can_introspect_autofield = True
     supports_subqueries_in_group_by = False
     supports_transactions = True
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index df3710f66baf..d3552ec643eb 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -248,17 +248,18 @@ def convert_empty_bytes(value, expression, connection):
     def deferrable_sql(self):
         return " DEFERRABLE INITIALLY DEFERRED"
 
-    def fetch_returned_insert_columns(self, cursor):
-        value = cursor._insert_id_var.getvalue()
-        if value is None or value == []:
-            # cx_Oracle < 6.3 returns None, >= 6.3 returns empty list.
-            raise DatabaseError(
-                'The database did not return a new row id. Probably "ORA-1403: '
-                'no data found" was raised internally but was hidden by the '
-                'Oracle OCI library (see https://code.djangoproject.com/ticket/28859).'
-            )
-        # cx_Oracle < 7 returns value, >= 7 returns list with single value.
-        return value if isinstance(value, list) else [value]
+    def fetch_returned_insert_columns(self, cursor, r_params):
+        for param in r_params:
+            value = param.bound_param.getvalue()
+            if value is None or value == []:
+                # cx_Oracle < 6.3 returns None, >= 6.3 returns empty list.
+                raise DatabaseError(
+                    'The database did not return a new row id. Probably "ORA-1403: '
+                    'no data found" was raised internally but was hidden by the '
+                    'Oracle OCI library (see https://code.djangoproject.com/ticket/28859).'
+                )
+            # cx_Oracle < 7 returns value, >= 7 returns list with single value.
+            yield value[0] if isinstance(value, list) else value
 
     def field_cast_sql(self, db_type, internal_type):
         if db_type and db_type.endswith('LOB'):
@@ -344,11 +345,19 @@ def regex_lookup(self, lookup_type):
     def return_insert_columns(self, fields):
         if not fields:
             return '', ()
-        sql = 'RETURNING %s.%s INTO %%s' % (
-            self.quote_name(fields[0].model._meta.db_table),
-            self.quote_name(fields[0].column),
-        )
-        return sql, (InsertVar(fields[0]),)
+        field_names = []
+        params = []
+        for field in fields:
+            field_names.append("%s.%s" % (
+                self.quote_name(field.model._meta.db_table),
+                self.quote_name(field.column)
+            ))
+            params.append(InsertVar(field))
+
+        return ('RETURNING %s INTO %s' % (
+            ', '.join(field_names),
+            ', '.join('%s' for _ in params)
+        ), tuple(params))
 
     def __foreign_key_constraints(self, table_name, recursive):
         with self.connection.cursor() as cursor:
diff --git a/django/db/backends/oracle/utils.py b/django/db/backends/oracle/utils.py
index fdd6dee61729..c8f8c2aacd40 100644
--- a/django/db/backends/oracle/utils.py
+++ b/django/db/backends/oracle/utils.py
@@ -27,11 +27,11 @@ class InsertVar:
     def __init__(self, field):
         internal_type = getattr(field, 'target_field', field).get_internal_type()
         self.db_type = self.types.get(internal_type, str)
+        self.bound_param = None
 
     def bind_parameter(self, cursor):
-        param = cursor.cursor.var(self.db_type)
-        cursor._insert_id_var = param
-        return param
+        self.bound_param = cursor.cursor.var(self.db_type)
+        return self.bound_param
 
 
 class Oracle_datetime(datetime.datetime):
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 5193362a92cd..5f8d4165fe82 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -1160,6 +1160,7 @@ def explain_query(self):
 
 class SQLInsertCompiler(SQLCompiler):
     returning_fields = None
+    r_params = tuple()
 
     def field_as_sql(self, field, val):
         """
@@ -1308,10 +1309,10 @@ def as_sql(self):
                 result.append(ignore_conflicts_suffix_sql)
             # Skip empty r_sql to allow subclasses to customize behavior for
             # 3rd party backends. Refs #19096.
-            r_sql, r_params = self.connection.ops.return_insert_columns(self.returning_fields)
+            r_sql, self.r_params = self.connection.ops.return_insert_columns(self.returning_fields)
             if r_sql:
                 result.append(r_sql)
-                params += [r_params]
+                params += [self.r_params]
             return [(" ".join(result), tuple(chain.from_iterable(params)))]
 
         if can_bulk:
@@ -1350,7 +1351,7 @@ def execute_sql(self, returning_fields=None):
                         'not supported on this database backend.'
                     )
                 assert len(self.query.objs) == 1
-                return self.connection.ops.fetch_returned_insert_columns(cursor)
+                return self.connection.ops.fetch_returned_insert_columns(cursor, self.r_params)
             return [self.connection.ops.last_insert_id(
                 cursor, self.query.get_meta().db_table, self.query.get_meta().pk.column
             )]
diff --git a/tests/queries/test_db_returning.py b/tests/queries/test_db_returning.py
index a8ac8394d2ec..5d4342cc1a17 100644
--- a/tests/queries/test_db_returning.py
+++ b/tests/queries/test_db_returning.py
@@ -1,4 +1,5 @@
 import datetime
+import unittest
 
 from django.db import NotSupportedError, connection
 from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
@@ -20,8 +21,8 @@ def test_insert_returning(self):
             captured_queries[-1]['sql'],
         )
 
-    @skipUnlessDBFeature('can_return_multiple_columns_from_insert')
-    def test_insert_returning_multiple(self):
+    @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific tests")
+    def test_insert_returning_multiple__pg(self):
         with CaptureQueriesContext(connection) as captured_queries:
             obj = ReturningModel.objects.create()
         table_name = connection.ops.quote_name(ReturningModel._meta.db_table)
@@ -37,6 +38,23 @@ def test_insert_returning_multiple(self):
         self.assertTrue(obj.pk)
         self.assertIsInstance(obj.created, datetime.datetime)
 
+    @unittest.skipUnless(connection.vendor == 'oracle', "Oracle specific tests")
+    def test_insert_returning_multiple__oracle(self):
+        with CaptureQueriesContext(connection) as captured_queries:
+            obj = ReturningModel.objects.create()
+        table_name = connection.ops.quote_name(ReturningModel._meta.db_table)
+        self.assertIn(
+            'RETURNING %s.%s, %s.%s INTO ' % (
+                table_name,
+                connection.ops.quote_name(ReturningModel._meta.get_field('id').column),
+                table_name,
+                connection.ops.quote_name(ReturningModel._meta.get_field('created').column),
+            ),
+            captured_queries[-1]['sql'],
+        )
+        self.assertTrue(obj.pk)
+        self.assertIsInstance(obj.created, datetime.datetime)
+
     @skipIfDBFeature('can_return_multiple_columns_from_insert')
     def test_insert_returning_multiple_not_supported(self):
         msg = (
