This document details the similarities and differences in SQL syntax between Oracle and BigQuery to help you plan your migration. Use batch SQL translation to migrate your SQL scripts in bulk, or interactive SQL translation to translate ad-hoc queries.
This section shows equivalents between data types in Oracle and in BigQuery.
VARCHAR2
STRING
NVARCHAR2
STRING
CHAR
STRING
NCHAR
STRING
CLOB
STRING
NCLOB
STRING
INTEGER
INT64
SHORTINTEGER
INT64
LONGINTEGER
INT64
NUMBER
NUMERIC
ROUND() function.
NUMBER(*, x)
NUMERIC
ROUND() function.
NUMBER(x, -y)
INT64
INT64 results in an error. In this case, ROUND() function should be applied.
BigQuery INT64 data types allow up to 18 digits of precision. If a number field has more than 18 digits, FLOAT64 data type should be used in BigQuery.
NUMBER(x)
INT64
INT64 results in an error. In this case, ROUND() function should be applied.
BigQuery INT64 data types allow up to 18 digits of precision. If a number field has more than 18 digits, FLOAT64 data type should be used in BigQuery.
FLOAT
FLOAT64/NUMERIC
FLOAT is an exact data type, and it's a NUMBER subtype in Oracle. In BigQuery, FLOAT64 is an approximate data type. NUMERIC may be a better match for FLOAT type in BigQuery.
BINARY_DOUBLE
FLOAT64/NUMERIC
FLOAT is an exact data type, and it's a NUMBER subtype in Oracle. In BigQuery, FLOAT64 is an approximate data type. NUMERIC may be a better match for FLOAT type in BigQuery.
BINARY_FLOAT
FLOAT64/NUMERIC
FLOAT is an exact data type, and it's a NUMBER subtype in Oracle. In BigQuery, FLOAT64 is an approximate data type. NUMERIC may be a better match for FLOAT type in BigQuery.
LONG
BYTES
LONG data type is used in earlier versions and is not suggested in new versions of Oracle Database.
BYTES data type in BigQuery can be used if it is necessary to hold LONG data in BigQuery. A better approach would be putting binary objects in Cloud Storage and holding references in BigQuery.
BLOB
BYTES
BYTES data type can be used to store variable-length binary data. If this field is not queried and not used in analytics, a better option is to store binary data in Cloud Storage.
BFILE
STRING
STRING data type can be used for referencing files in a BigQuery table.
DATE
DATETIME
TIMESTAMP
TIMESTAMP
BigQuery supports a time zone region name from a TZ database and time zone offset from UTC.
In BigQuery a time zone conversion should be manually performed to match Oracle'sTIMESTAMP WITH LOCAL TIME ZONE feature.
TIMESTAMP(x)
TIMESTAMP
BigQuery supports a time zone region name from a TZ database and time zone offset from UTC.
In BigQuery a time zone conversion should be manually performed to match Oracle'sTIMESTAMP WITH LOCAL TIME ZONE feature.
TIMESTAMP WITH TIME ZONE
TIMESTAMP
BigQuery supports a time zone region name from a TZ database and time zone offset from UTC.
In BigQuery a time zone conversion should be manually performed to match Oracle'sTIMESTAMP WITH LOCAL TIME ZONE feature.
TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP
BigQuery supports a time zone region name from a TZ database and time zone offset from UTC.
In BigQuery a time zone conversion should be manually performed to match Oracle's TIMESTAMP WITH LOCAL TIME ZONE feature.
INTERVAL YEAR TO MONTH
STRING
STRING data type in BigQuery.
INTERVAL DAY TO SECOND
STRING
STRING data type in BigQuery.
RAW
BYTES
BYTES data type can be used to store variable-length binary data. If this field is not queried and used in analytics, a better option is to store binary data on Cloud Storage.
LONG RAW
BYTES
BYTES data type can be used to store variable-length binary data. If this field is not queried and used in analytics, a better option is to store binary data on Cloud Storage.
ROWID
STRING
ROWID or UROWID field should not be used in applications. But if this is the case, STRING data type can be used to hold this data.
Oracle SQL uses a set of default formats set as parameters for displaying
expressions and column data, and for conversions between data types. For
example, NLS_DATE_FORMAT set as YYYY/MM/DD formats dates as YYYY/MM/DD
by default. You can find more information about the NLS settings in the Oracle
online documentation.
In BigQuery, there are no initialization parameters.
By default, BigQuery expects all source data to be UTF-8 encoded when loading. Optionally, if you have CSV files with data encoded in ISO-8859-1 format, you can explicitly specify the encoding when you import your data so that BigQuery can properly convert your data to UTF-8 during the import process.
It is only possible to import data that is ISO-8859-1 or UTF-8
encoded. BigQuery stores and returns the data as UTF-8 encoded.
Intended date format or time zone can be set in
DATE and
TIMESTAMP
functions.
When you convert timestamp and date formatting elements from Oracle to
BigQuery, you must pay attention to time zone differences between
TIMESTAMP and DATETIME as summarized in the following table.
Notice there are no parentheses in the Oracle formats because the formats
(CURRENT_*) are keywords, not functions.
CURRENT_TIMESTAMP
TIMESTAMP information in Oracle can have different time zone
information, which is defined using WITH TIME ZONE in column
definition or setting TIME_ZONE
variable.
CURRENT_TIMESTAMP()
function, which is
formatted in ISO format. However, the output format does always show the
UTC time zone. (Internally, BigQuery does not have a time
zone.)
Note the following details on differences in the ISO format:
DATETIME is formatted based on output channel conventions. In the BigQuery command-line tool and BigQuery console DATETIME is formatted using a T separator according to RFC 3339. However, in Python and Java JDBC, a space is used as a separator.
FORMAT_DATETIME() function, which makes an explicit cast a string. For example, the following expression always returns a space separator:
CAST(CURRENT_DATETIME() AS STRING)
CURRENT_DATE
SYSDATE
SYSDATE or CURRENT_DATE
DATE format that always returns a date in ISO 8601 format.
DATE_FROM_UNIX_DATE can't be used because it is 1970-based.
CURRENT_DATE-3
DATE_ADD() or DATE_SUB().
BigQuery uses arithmetic operators for data types: INT64, NUMERIC, and FLOAT64.
NLS_DATE_FORMAT
This section addresses differences in query syntax between Oracle and BigQuery.
SELECT statementsMost Oracle SELECT statements are compatible with BigQuery.
The following sections list mappings between Oracle functions and BigQuery equivalents.
Oracle and BigQuery comparison operators are ANSI SQL:2011
compliant. The comparison operators in the table below are the same in both
BigQuery and Oracle. You can use
REGEXP_CONTAINS
instead of REGEXP_LIKE in BigQuery.
| Operator | Description |
|---|---|
"="
|
Equal |
<>
|
Not equal |
!=
|
Not equal |
>
|
Greater than |
>=
|
Greater than or equal |
<
|
Less than |
<=
|
Less than or equal |
IN ( )
|
Matches a value in a list |
NOT
|
Negates a condition |
BETWEEN
|
Within a range (inclusive) |
IS NULL
|
NULL value
|
IS NOT NULL
|
Not NULL value
|
LIKE
|
Pattern matching with % |
EXISTS
|
Condition is met if subquery returns at least one row |
The operators on the table are the same both in BigQuery and Oracle.
The following table shows mappings between common Oracle aggregate, statistical aggregate, and approximate aggregate functions with their BigQuery equivalents:
ANY_VALUEANY_VALUEAPPROX_COUNT
HLL_COUNT set of functions with specified precision
APPROX_COUNT_DISTINCT
APPROX_COUNT_DISTINCT
APPROX_COUNT_DISTINCT_AGG
APPROX_COUNT_DISTINCT
APPROX_COUNT_DISTINCT_DETAIL
APPROX_COUNT_DISTINCT
APPROX_PERCENTILE(percentile) WITHIN GROUP (ORDER BY expression)
APPROX_QUANTILES(expression, 100)[
OFFSET(CAST(TRUNC(percentile * 100) as INT64))]APPROX_PERCENTILE_AGG
APPROX_QUANTILES(expression, 100)[
OFFSET(CAST(TRUNC(percentile * 100) as INT64))]
APPROX_PERCENTILE_DETAIL
APPROX_QUANTILES(expression, 100)[OFFSET(CAST(TRUNC(percentile * 100) as INT64))]
APPROX_SUM
APPROX_TOP_SUM(expression, weight, number)
AVG
AVG
BIT_COMPLEMENT
BIT_OR
BIT_OR, X | Y
BIT_XOR
BIT_XOR, X ^ Y
BITAND
BIT_AND, X & Y
CARDINALITY
COUNT
COLLECT
TYPE AS TABLE OF.
Consider using STRING_AGG() or ARRAY_AGG() in
BigQuery
CORR/CORR_K/
CORR_S
CORR
COUNT
COUNT
COVAR_POP
COVAR_POP
COVAR_SAMP
COVAR_SAMP
FIRST
GROUP_ID
GROUPING
GROUPING
GROUPING_ID
LAST
LISTAGG
STRING_AGG, ARRAY_CONCAT_AGG(expression [ORDER BY key [{ASC|DESC}] [, ... ]] [LIMIT n])
MAX
MAX
MIN
MIN
OLAP_CONDITION
OLAP_EXPRESSION
OLAP_EXPRESSION_BOOL
OLAP_EXPRESSION_DATE
OLAP_EXPRESSION_TEXT
OLAP_TABLE
POWERMULTISET
POWERMULTISET_BY_CARDINALITY
QUALIFY
REGR_AVGX
AVG(IF(dep_var_expr is NULLOR ind_var_expr is NULL,NULL, ind_var_expr))
REGR_AVGY
AVG(IF(dep_var_expr is NULLOR ind_var_expr is NULL,NULL, dep_var_expr))
REGR_COUNT
SUM(IF(dep_var_expr is NULLOR ind_var_expr is NULL,NULL, 1))
REGR_INTERCEPT
AVG(dep_var_expr)
- AVG(ind_var_expr)
* (COVAR_SAMP(ind_var_expr,dep_var_expr)
/ VARIANCE(ind_var_expr)
)
REGR_R2
(COUNT(dep_var_expr) *
SUM(ind_var_expr * dep_var_expr) -
SUM(dep_var_expr) * SUM(ind_var_expr))
/ SQRT(
(COUNT(ind_var_expr) *
SUM(POWER(ind_var_expr, 2)) *
POWER(SUM(ind_var_expr),2)) *
(COUNT(dep_var_expr) *
SUM(POWER(dep_var_expr, 2)) *
POWER(SUM(dep_var_expr), 2)))
REGR_SLOPE
COVAR_SAMP(ind_var_expr,
dep_var_expr)
/ VARIANCE(ind_var_expr)
REGR_SXX
SUM(POWER(ind_var_expr, 2)) - COUNT(ind_var_expr) * POWER(AVG(ind_var_expr),2)
REGR_SXY
SUM(ind_var_expr*dep_var_expr) - COUNT(ind_var_expr) * AVG(ind) * AVG(dep_var_expr)
REGR_SYY
SUM(POWER(dep_var_expr, 2)) - COUNT(dep_var_expr) * POWER(AVG(dep_var_expr),2)
ROLLUP
ROLLUP
STDDEV_POP
STDDEV_POP
STDDEV_SAMP
STDDEV_SAMP, STDDEV
SUM
SUM
VAR_POP
VAR_POP
VAR_SAMP
VAR_SAMP, VARIANCE
WM_CONCAT
STRING_AGG
BigQuery offers the following additional aggregate functions:
The following table shows mappings between common Oracle analytic and aggregate analytic functions with their BigQuery equivalents.
AVG
AVG
BIT_COMPLEMENT
BIT_OR
BIT_OR, X | Y
BIT_XOR
BIT_XOR, X ^ Y
BITAND
BIT_AND, X & Y
BOOL_TO_INT
CAST(X AS INT64)
COUNT
COUNT
COVAR_POP
COVAR_POP
COVAR_SAMP
COVAR_SAMP
CUBE_TABLE
CUME_DIST
DENSE_RANK(ANSI)
DENSE_RANK
FEATURE_COMPARE
FEATURE_DETAILS
FEATURE_ID
FEATURE_SET
FEATURE_VALUE
FIRST_VALUE
FIRST_VALUE
HIER_CAPTION
HIER_CHILD_COUNT
HIER_COLUMN
HIER_DEPTH
HIER_DESCRIPTION
HIER_HAS_CHILDREN
HIER_LEVEL
HIER_MEMBER_NAME
HIER_ORDER
HIER_UNIQUE_MEMBER_NAME
LAST_VALUE
LAST_VALUE
LAG
LAG
LEAD
LEAD
LISTAGG
ARRAY_AGG
STRING_AGG
ARRAY_CONCAT_AGG
MATCH_NUMBER
MATCH_RECOGNIZE
MAX
MAX
MEDIAN
PERCENTILE_CONT(x, 0.5 RESPECT NULLS) OVER()
MIN
MIN
NTH_VALUE
NTH_VALUE (value_expression, constant_integer_expression [{RESPECT | IGNORE} NULLS])
NTILE
NTILE(constant_integer_expression)
PERCENT_RANK
PERCENT_RANKM
PERCENT_RANK
PERCENTILE_CONT
PERCENTILE_DISC
PERCENTILE_CONT
PERCENTILE_CONT
PERCENTILE_DISC
PERCENTILE_DISC
PRESENTNNV
PRESENTV
PREVIOUS
RANK(ANSI)
RANK
RATIO_TO_REPORT(expr) OVER (partition clause)
expr / SUM(expr) OVER (partition clause)
ROW_NUMBER
ROW_NUMBER
STDDEV_POP
STDDEV_POP
STDDEV_SAMP
STDDEV_SAMP, STDDEV
SUM
SUM
VAR_POP
VAR_POP
VAR_SAMP
VAR_SAMP, VARIANCE
VARIANCE
VARIANCE()
WIDTH_BUCKET
The following table shows mappings between common Oracle date/time functions and their BigQuery equivalents.
ADD_MONTHS(date, integer)
DATE_ADD(date, INTERVAL integer MONTH), TIMESTAMP you can use
EXTRACT(DATE FROM TIMESTAMP_ADD(date, INTERVAL integer MONTH))
CURRENT_DATE
CURRENT_DATE
CURRENT_TIME
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP
DATE - k
DATE_SUB(date_expression, INTERVAL k DAY)
DATE + k
DATE_ADD(date_expression, INTERVAL k DAY)
DBTIMEZONE
EXTRACT
EXTRACT(DATE), EXTRACT(TIMESTAMP)
LAST_DAY
DATE_SUB(
DATE_TRUNC(
DATE_ADD(
date_expression,
INTERVAL 1 MONTH
),
MONTH
),
INTERVAL 1 DAY
)
LOCALTIMESTAMP
MONTHS_BETWEEN
DATE_DIFF(date_expression, date_expression, MONTH)
NEW_TIME
DATE(timestamp_expression, time zone)
TIME(timestamp, time zone)
DATETIME(timestamp_expression, time zone)
NEXT_DAY
DATE_ADD(
DATE_TRUNC(
date_expression,
WEEK(day_value)
),
INTERVAL 1 WEEK
)
SYS_AT_TIME_ZONE
CURRENT_DATE([time_zone])
SYSDATE
CURRENT_DATE()
SYSTIMESTAMP
CURRENT_TIMESTAMP()
TO_DATE
PARSE_DATE
TO_TIMESTAMP
PARSE_TIMESTAMP
TO_TIMESTAMP_TZ
PARSE_TIMESTAMP
TZ_OFFSET
WM_CONTAINSWM_EQUALSWM_GREATERTHANWM_INTERSECTIONWM_LDIFFWM_LESSTHANWM_MEETSWM_OVERLAPSWM_RDIFFBigQuery offers the following additional date/time functions:
CURRENT_DATETIMEDATE_FROM_UNIX_DATEDATE_TRUNCDATETIMEDATETIME_ADDDATETIME_DIFFDATETIME_SUBDATETIME_TRUNCFORMAT_DATEFORMAT_DATETIMEThe following table shows mappings between Oracle string functions and their BigQuery equivalents:
ASCII
TO_CODE_POINTS(string_expr)[OFFSET(0)]
ASCIISTR
RAWTOHEX
TO_HEX
LENGTH
CHAR_LENGTH
LENGTH
CHARACTER_LENGTH
CHR
CODE_POINTS_TO_STRING(
[mod(numeric_expr, 256)]
)
COLLATION
COMPOSE
CONCAT, (|| operator)
CONCAT
DECOMPOSE
ESCAPE_REFERENCE (UTL_I18N)
INITCAP
INITCAP
INSTR/INSTR2/INSTR4/INSTRB/INSTRC
LENGTH/LENGTH2/LENGTH4/LENGTHB/LENGTHC
LENGTH
LOWER
LOWER
LPAD
LPAD
LTRIM
LTRIM
NLS_INITCAP
NLS_LOWER
LOWER
NLS_UPPER
UPPER
NLSSORT
POSITION
STRPOS(string, substring)
PRINTBLOBTOCLOB
REGEXP_COUNT
ARRAY_LENGTH(REGEXP_EXTRACT_ALL(value, regex))
REGEXP_INSTR
STRPOS(source_string, REGEXP_EXTRACT(source_string, regexp_string))
Note: Returns first occurrence.
REGEXP_REPLACE
REGEXP_REPLACE
REGEXP_LIKE
IF(REGEXP_CONTAINS,1,0)
REGEXP_SUBSTR
REGEXP_EXTRACT, REGEXP_EXTRACT_ALL
REPLACE
REPLACE
REVERSE
REVERSE
RIGHT
SUBSTR(source_string, -1, length)
RPAD
RPAD
RTRIM
RTRIM
SOUNDEX
STRTOK
SPLIT(instring, delimiter)[ORDINAL(tokennum)]
Note: The entire delimiter string argument is used as a single delimiter. The default delimiter is a comma.
SUBSTR/SUBSTRB/SUBSTRC/SUBSTR2/SUBSTR4
SUBSTR
TRANSLATE
REPLACE
TRANSLATE USING
REPLACE
TRIM
TRIM
UNISTR
CODE_POINTS_TO_STRING
UPPER
UPPER
|| (VERTICAL BARS)
CONCAT
BigQuery offers the following additional string functions:
BYTE_LENGTHCODE_POINTS_TO_BYTESENDS_WITHFROM_BASE32FROM_BASE64FROM_HEXNORMALIZENORMALIZE_AND_CASEFOLDREPEATSAFE_CONVERT_BYTES_TO_STRINGSPLITSTARTS_WITHSTRPOSTO_BASE32TO_BASE64TO_CODE_POINTSThe following table shows mappings between Oracle math functions and their BigQuery equivalents.
ABS
ABS
ACOS
ACOS
ACOSH
ACOSH
ASIN
ASIN
ASINH
ASINH
ATAN
ATAN
ATAN2
ATAN2
ATANH
ATANH
CEIL
CEIL
CEILING
CEILING
COS
COS
COSH
COSH
EXP
EXP
FLOOR
FLOOR
GREATEST
GREATEST
LEAST
LEAST
LN
LN
LNNVL
ISNULL
LOG
LOG
MOD (% operator)
MOD
POWER (** operator)
POWER, POW
DBMS_RANDOM.VALUE
RAND
RANDOMBYTES
RANDOMINTEGER
CAST(FLOOR(10*RAND()) AS INT64)
RANDOMNUMBER
REMAINDER
MOD
ROUND
ROUND
ROUND_TIES_TO_EVEN
ROUND()
SIGN
SIGN
SIN
SIN
SINH
SINH
SQRT
SQRT
STANDARD_HASH
FARM_FINGERPRINT, MD5, SHA1, SHA256, SHA512
STDDEV
TAN
TAN
TANH
TANH
TRUNC
NVL
IFNULL(expr, 0), COALESCE(exp, 0)
BigQuery offers the following additional math functions:
The following table shows mappings between Oracle type conversion functions and their BigQuery equivalents.
BIN_TO_NUM
SAFE_CONVERT_BYTES_TO_STRING(value)
BINARY2VARCHAR
SAFE_CONVERT_BYTES_TO_STRING(value)
CAST
CAST_FROM_BINARY_DOUBLE
CAST_FROM_BINARY_FLOAT
CAST_FROM_BINARY_INTEGER
CAST_FROM_NUMBER
CAST_TO_BINARY_DOUBLE
CAST_TO_BINARY_FLOAT
CAST_TO_BINARY_INTEGER
CAST_TO_NUMBER
CAST_TO_NVARCHAR2
CAST_TO_RAW
>CAST_TO_VARCHAR
CAST(expr AS typename)
CHARTOROWID
CONVERT
EMPTY_BLOB
BLOB is not used in BigQuery.
EMPTY_CLOB
CLOB is not used in BigQuery.
FROM_TZ
INT_TO_BOOL
CAST
IS_BIT_SET
NCHR
NUMTODSINTERVAL
INTERVAL data type is not supported in BigQuery
NUMTOHEX
TO_HEX function
NUMTOHEX2
NUMTOYMINTERVAL
INTERVAL data type is not supported in BigQuery.
RAW_TO_CHAR
RAW_TO_NCHAR
RAW_TO_VARCHAR2
RAWTOHEX
RAWTONHEX
RAWTONUM
RAWTONUM2
RAWTOREF
REFTOHEX
REFTORAW
ROWIDTOCHAR
ROWID is Oracle specific type and does not exist in BigQuery. This value should
be represented as string.
ROWIDTONCHAR
ROWID is Oracle specific type and does not exist in BigQuery. This value should
be represented as string.
SCN_TO_TIMESTAMP
SCN is Oracle specific type and does not exist in BigQuery. This value should be represented as timestamp.
TO_ACLID
TO_ANYLOB
TO_APPROX_COUNT_DISTINCT
TO_APPROX_PERCENTILE
TO_BINARY_DOUBLE
TO_BINARY_FLOAT
TO_BLOB
TO_CHAR
TO_CLOB
TO_DATE
TO_DSINTERVAL
TO_LOB
TO_MULTI_BYTE
TO_NCHAR
TO_NCLOB
TO_NUMBER
TO_RAW
TO_SINGLE_BYTE
TO_TIMECAST(expr AS typename)PARSE_DATEPARSE_TIMESTAMPTREAT
VALIDATE_CONVERSION
VSIZE
The following table shows mappings between Oracle JSON functions and their BigQuery equivalents.
| Oracle | BigQuery |
|---|---|
AS_JSON
|
TO_JSON_STRING(value[, pretty_print])
|
JSON_ARRAY
|
Consider using UDFs and TO_JSON_STRING function
|
JSON_ARRAYAGG
|
Consider using UDFs and TO_JSON_STRING function
|
JSON_DATAGUIDE
|
Custom user-defined function. |
JSON_EQUAL
|
Custom user-defined function. |
JSON_EXIST
|
Consider using UDFs and JSON_EXTRACT or JSON_EXTRACT_SCALAR
|
JSON_MERGEPATCH
|
Custom user-defined function. |
JSON_OBJECT
|
Is not supported by BigQuery. |
JSON_OBJECTAGG
|
Is not supported by BigQuery. |
JSON_QUERY
|
Consider using UDFs and JSON_EXTRACT or JSON_EXTRACT_SCALAR.
|
JSON_TABLE
|
Custom user-defined function. |
JSON_TEXTCONTAINS
|
Consider using UDFs and JSON_EXTRACT or JSON_EXTRACT_SCALAR.
|
JSON_VALUE
|
JSON_EXTRACT_SCALAR
|
BigQuery does not provide implicit XML functions. XML can be loaded to BigQuery as string and UDFs can be used to parse XML. Alternatively, XML processing be done by an ETL/ELT tool such as Dataflow. The following list shows Oracle XML functions:
DELETEXML
ENCODE_SQL_XMLEXISTSNODEEXTRACTCLOBXMLEXTRACTVALUEINSERTCHILDXMLINSERTCHILDXMLAFTERINSERTCHILDXMLBEFOREINSERTXMLAFTERINSERTXMLBEFORESYS_XMLAGGSYS_XMLANALYZESYS_XMLCONTAINSSYS_XMLCONVSYS_XMLEXNSURISYS_XMLGENSYS_XMLI_LOC_ISNODESYS_XMLI_LOC_ISTEXTSYS_XMLINSTRSYS_XMLLOCATOR_GETSVALSYS_XMLNODEIDSYS_XMLNODEID_GETLOCATORSYS_XMLNODEID_GETOKEYSYS_XMLNODEID_GETPATHIDSYS_XMLNODEID_GETPTRIDSYS_XMLNODEID_GETRIDSYS_XMLNODEID_GETSVALSYS_XMLT_2_SCSYS_XMLTRANSLATESYS_XMLTYPE2SQLUPDATEXMLXML2OBJECTXMLCASTXMLCDATAXMLCOLLATVALXMLCOMMENTXMLCONCATXMLDIFFXMLELEMENTXMLEXISTSXMLEXISTS2XMLFORESTXMLISNODEXMLISVALIDXMLPARSEXMLPATCHXMLPIXMLQUERYXMLQUERYVALXMLSERIALIZEXMLTABLEXMLTOJSONXMLTRANSFORMXMLTRANSFORMBLOBXMLTYPEMachine learning (ML) functions in Oracle and BigQuery are
different.
Oracle requires advanced analytics pack and licenses to do ML on the database.
Oracle uses the DBMS_DATA_MINING package for ML. Converting Oracle data miner
jobs requires rewriting the code to work with BigQuery features.
You can choose from comprehensive
Google AI offerings, including the
following products and features:
You can use BigQuery ML or Agent Platform development tools to develop, train, and evaluate ML models.
The following table shows Oracle ML functions:
| Oracle | BigQuery |
|---|---|
CLASSIFIER
|
See BigQuery ML for machine learning classifier and regression options |
CLUSTER_DETAILS
|
|
CLUSTER_DISTANCE
|
|
CLUSTER_ID
|
|
CLUSTER_PROBABILITY
|
|
CLUSTER_SET
|
|
PREDICTION
|
|
PREDICTION_BOUNDS
|
|
PREDICTION_COST
|
|
PREDICTION_DETAILS
|
|
PREDICTION_PROBABILITY
|
|
PREDICTION_SET
|
The following table shows the functions for identifying the user in Oracle and BigQuery:
| Oracle | BigQuery |
|---|---|
UID
|
SESSION_USER
|
USER/SESSION_USER/CURRENT_USER
|
SESSION_USER()
|
The following table shows set or array functions in Oracle and their equivalents in BigQuery:
| Oracle | BigQuery |
|---|---|
MULTISET
|
ARRAY_AGG
|
MULTISET EXCEPT
|
ARRAY_AGG([DISTINCT] expression)
|
MULTISET INTERSECT
|
ARRAY_AGG([DISTINCT])
|
MULTISET UNION
|
ARRAY_AGG
|
The following table shows window functions in Oracle and their equivalents in BigQuery.
| Oracle | BigQuery |
|---|---|
LAG
|
LAG (value_expression[, offset [, default_expression]])
|
LEAD
|
LEAD (value_expression[, offset [, default_expression]])
|
Hierarchical or recursive queries are not used in BigQuery. If the depth of the hierarchy is known similar functionality can be achieved with joins, as illustrated in the following example. Another solution would be to utilize the BigQueryStorage API and Spark.
select
array(
select e.update.element
union all
select c1 from e.update.element.child as c1
union all
select c2 from e.update.element.child as c1, c1.child as c2
union all
select c3 from e.update.element.child as c1, c1.child as c2, c2.child as c3
union all
select c4 from e.update.element.child as c1, c1.child as c2, c2.child as c3, c3.child as c4
union all
select c5 from e.update.element.child as c1, c1.child as c2, c2.child as c3, c3.child as c4, c4.child as c5
) as flattened,
e as event
from t, t.events as e
The following table shows hierarchical functions in Oracle.
| Oracle | BigQuery |
|---|---|
DEPTH
|
Hierarchical queries are not used in BigQuery. |
PATH
|
|
SYS_CONNECT_BY_PATH (hierarchical)
|
UTL_File
package is mainly used for reading and writing the operating system files from
PL/SQL. Cloud Storage can be used for any kind of raw file staging.
External tables and BigQuery
load and export
should be used to read and write files from and to Cloud Storage. For
more information, see
Introduction to external data sources.
You can use BigQuery geospatial analytics to replace spatial
functionality. There
are SDO_* functions and types in Oracle such as SDO_GEOM_KEY,
SDO_GEOM_MBR, SDO_GEOM_MMB. These functions are used for spatial
analysis. You can use geospatial analytics
to do spatial analysis.
This section addresses differences in data management language syntax between Oracle and BigQuery.
INSERT statementMost Oracle INSERT statements are compatible with BigQuery. The
following table shows exceptions.
DML scripts in BigQuery have slightly different consistency
semantics than the equivalent statements in Oracle. For an overview of snapshot
isolation and session and transaction handling, see the CREATE [UNIQUE] INDEX
section elsewhere in this document.
INSERT INTO table VALUES (...);
INSERT INTO table (...) VALUES (...);
Oracle offers a DEFAULT keyword for non-nullable columns.
INSERT statement only works if values for all columns in the target table are included in ascending order based on their ordinal positions.
INSERT INTO table VALUES (1,2,3);
INSERT INTO table VALUES (4,5,6);
INSERT INTO table VALUES (7,8,9);
INSERT ALL
INTO table (col1, col2) VALUES ('val1_1', 'val1_2')
INTO table (col1, col2) VALUES ('val2_1', 'val2_2')
INTO table (col1, col2) VALUES ('val3_1', 'val3_2')
.
.
.
SELECT 1 FROM DUAL;
INSERT INTO table VALUES (1,2,3),
(4,5,6),
(7,8,9);
BigQuery imposes DML quotas, which restrict the number of DML statements you can execute daily. To make the best use of your quota, consider the following approaches:
INSERT statement, instead of
one row per INSERT operation.
INSERT) using a
MERGE statement.
CREATE TABLE ... AS SELECT to create and populate new
tables.UPDATE statementOracle UPDATE statements are mostly compatible with BigQuery,
however, in BigQuery the UPDATE statement must have a WHERE
clause.
As a best practice, you should prefer batch DML statements over multiple single
UPDATE and INSERT statements. DML scripts in BigQuery have
slightly different consistency semantics than equivalent statements in Oracle.
For an overview on snapshot isolation and session and transaction handling see
the CREATE INDEX section in this document.
The following table shows Oracle UPDATE statements and BigQuery
statements that accomplish the same tasks.
In BigQuery the UPDATE statement must have a WHERE clause.
For more information about UPDATE in BigQuery, see the
BigQuery UPDATE examples
in the DML documentation.
DELETE and TRUNCATE statementsThe DELETE and TRUNCATE statements are both ways to remove rows from a table
without affecting the table schema. TRUNCATE is not used in BigQuery.
However, you can use DELETE statements to achieve the same effect.
In BigQuery, the DELETE statement must have a WHERE clause.
For more information about DELETE in BigQuery, see the
BigQuery DELETE examples
in the DML documentation.
| Oracle | BigQuery |
|---|---|
DELETE database.table;
|
DELETE FROM table WHERE TRUE;
|
MERGE statementThe MERGE statement can combine INSERT, UPDATE, and DELETE operations
into a single UPSERT statement and perform the operations atomically. The
MERGE operation must match, at most, one source row for each target row.
BigQuery and Oracle both follow ANSI Syntax.
However, DML scripts in BigQuery have slightly different consistency semantics than the equivalent statements in Oracle.
This section addresses differences in data definition language syntax between Oracle and BigQuery.
CREATE TABLE statementMost Oracle CREATE TABLE
statements are compatible with BigQuery, except for the following
constraints and syntax elements, which are not used in BigQuery:
STORAGETABLESPACEDEFAULTGENERATED ALWAYS ASENCRYPTPRIMARY KEY (col, ...). For more information, see
CREATE INDEX.UNIQUE INDEX. For more information, see
CREATE INDEX.CONSTRAINT..REFERENCESDEFAULTPARALLELCOMPRESSFor more information about CREATE TABLE in BigQuery,
see the BigQuery CREATE TABLE
examples.
Identity columns are introduced with Oracle 12c version which enables auto-increment on a column. This is not used in BigQuery, this can be achieved with the following batch way. For more information about surrogate keys and slowly changing dimensions (SCD), refer to the following guides:
| Oracle | BigQuery |
|---|---|
CREATE TABLE table (
|
INSERT INTO dataset.table SELECT
|
Oracle uses Comment syntax to add comments on columns. This feature can be
similarly implemented in BigQuery using the column description as
shown in the following table:
| Oracle | BigQuery |
|---|---|
Comment on column table is 'column desc';
|
CREATE TABLE dataset.table (
|
Oracle supports temporary tables, which are often used to store intermediate results in scripts. Temporary tables are supported in BigQuery.
| Oracle | BigQuery |
|---|---|
CREATE GLOBAL TEMPORARY TABLE
|
CREATE TEMP TABLE temp_tab
|
The following Oracle elements are not used in BigQuery:
ON COMMIT DELETE ROWS;ON COMMIT PRESERVE ROWS;There are also some other ways to emulate temporary tables in BigQuery:
temp to clearly denote that
the tables are temporary.Table TTL: Create a table that has a table-specific short time to live using DDL statements similar to the following:
CREATE TABLE temp.name (col1, col2, ...)
OPTIONS(expiration_timestamp=TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR));
WITH clause: If a temporary table is needed only within the same
block, use a temporary result using a WITH
statement or subquery.
CREATE SEQUENCE statementSequences are not used in BigQuery, this can be achieved with the following batch way. For more information about surrogate keys and slowly changing dimensions (SCD), refer to the following guides:
INSERT INTO dataset.table
SELECT *,
ROW_NUMBER() OVER () AS id
FROM dataset.table
CREATE VIEW statementThe following table shows equivalents between Oracle and BigQuery
for the CREATE VIEW statement.
| Oracle | BigQuery | Notes |
|---|---|---|
CREATE VIEW view_name AS SELECT ...
|
CREATE VIEW view_name AS SELECT ...
|
|
CREATE OR REPLACE VIEW view_name AS SELECT ...
|
CREATE OR REPLACE VIEW
view_name AS
SELECT ...
|
|
| Not supported | CREATE VIEW IF NOT EXISTS
view_name
OPTIONS(view_option_list)
AS SELECT ...
|
Creates a new view only if the view does not currently exist in the specified dataset. |
CREATE MATERIALIZED VIEW statementIn BigQuery materialized view refresh operations are done automatically. There is no need to specify refresh options (for example, on commit or on schedule) in BigQuery. For more information, see Introduction to materialized views.
In case the base table keeps changing by appends only, the query that uses materialized view (whether view is explicitly referenced or selected by the query optimizer) scans all materialized view plus a delta in the base table since the last view refresh. This means queries are faster and cheaper.
On the contrary, if there were any updates (DML UPDATE / MERGE) or deletions (DML DELETE, truncation, partition expiration) in the base table since the last view refresh, the materialized view are not be scanned and hence query don't get any savings until the next view refresh. Basically, any update or deletion in the base table invalidates the materialized view state.
Also, the data from the streaming buffer of the base table is not saved into materialized view. Streaming buffer is still being scanned fully regardless of whether materialized view is used.
The following table shows equivalents between Oracle and BigQuery
for the CREATE MATERIALIZED VIEW statement.
| Oracle | BigQuery | Notes |
|---|---|---|
CREATE MATERIALIZED VIEW view_name
|
CREATE MATERIALIZED VIEW
|
CREATE [UNIQUE] INDEX statementThis section describes approaches in BigQuery for how to create functionality similar to indexes in Oracle.
BigQuery doesn't need explicit indexes, because it's a column-oriented database with query and storage optimization. BigQuery provides functionality such as partitioning and clustering as well as nested fields, which can increase query efficiency and performance by optimizing how data is stored.
In Oracle, a unique index can be used to prevent rows with non-unique keys in a table. If a process tries to insert or update data that has a value that's already in the index the operation fails with an index violation.
Because BigQuery doesn't provide explicit indexes, a MERGE
statement can be used instead to insert only unique records into a target table
from a staging table while discarding duplicate records. However, there is no
way to prevent a user with edit permissions from inserting a duplicate record.
To generate an error for duplicate records in BigQuery you can
use a MERGE statement from the staging table, as shown in the following
example:
MERGE `prototype.FIN_MERGE` t \
USING `prototype.FIN_TEMP_IMPORT` m \
ON t.col1 = m.col1 \
AND t.col2 = m.col2 \
WHEN MATCHED THEN \
UPDATE SET t.col1 = ERROR(CONCAT('Encountered Error for ', m.col1, ' ', m.col2)) \
WHEN NOT MATCHED THEN \
INSERT (col1,col2,col3,col4,col5,col6,col7,col8)
VALUES(col1,col2,col3,col4,col5,col6, CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
More often, users prefer to remove duplicates independently in order to find errors in downstream systems.
BigQuery does not support DEFAULT and IDENTITY (sequences) columns.
BigQuery doesn't have a lock mechanism like Oracle and can run concurrent queries (up to your quota). Only DML statements have certain concurrency limits and might require a table lock during execution in some scenarios.
This section describes how to convert procedural SQL statements used in stored procedures, functions and triggers from Oracle to BigQuery.
CREATE PROCEDURE statementStored Procedure is supported as part of BigQuery Scripting Beta.
| Oracle | BigQuery | Notes |
|---|---|---|
CREATE PROCEDURE
|
CREATE PROCEDURE
|
Similar to Oracle, BigQuery supports IN, OUT, INOUT argument modes. Other syntax specifications are not supported in BigQuery.
|
CREATE OR REPLACE PROCEDURE
|
CREATE OR REPLACE PROCEDURE
|
|
CALL
|
CALL
|
The sections that follow describe ways to convert existing Oracle procedural statements to BigQuery scripting statements that have similar functionality.
CREATE TRIGGER statementTriggers are not used in BigQuery. Row based application logic should be handled on the application layer. Trigger functionality can be achieved utilising the ingestion tool, Pub/Sub and/or Cloud Run functions during the ingestion time or utilising regular scans.
The following table shows Oracle DECLAREstatements and their
BigQuery equivalents.
| Oracle | BigQuery |
|---|---|
DECLARE
|
DECLARE L_VAR int64;
|
SET var = value;
|
SET var = value;
|
BigQuery does not support cursors, so the following statements are not used in BigQuery:
DECLARE cursor_name CURSOR [FOR | WITH] ...OPEN CUR_VAR FOR sql_str;OPEN cursor_name [USING var, ...];FETCH cursor_name INTO var, ...;CLOSE cursor_name;The following Oracle Dynamic SQL statement and its BigQuery equivalent:
| Oracle | BigQuery |
|---|---|
EXECUTE IMMEDIATE
sql_str
|
EXECUTE IMMEDIATE
|
The following table shows Oracle flow-of-control statements and their BigQuery equivalents.
| Oracle | BigQuery |
|---|---|
IF condition THEN
|
IF condition THEN
|
SET SERVEROUTPUT ON;
|
DECLARE x INT64 DEFAULT 0;
|
LOOP
|
LOOP
|
WHILE boolean_expression DO
|
WHILE boolean_expression DO
|
FOR LOOP
|
FOR LOOP is not used in BigQuery. Use other
LOOP statements.
|
BREAK
|
BREAK
|
CONTINUE
|
CONTINUE
|
CONTINUE/EXIT WHEN
|
Use CONTINUE with IF condition.
|
GOTO
|
GOTO statement does not exist in BigQuery. Use IF condition.
|
GATHER_STATS_JOB
LOCK TABLE table_name IN [SHARE/EXCLUSIVE] MODE NOWAIT;
Alter session set isolation_level=serializable; /
SET TRANSACTION ...
EXPLAIN PLAN ...
SELECT * FROM DBA_[*];
(Oracle DBA_/ALL_/V$ views)
SELECT * FROM mydataset.INFORMATION_SCHEMA.TABLES;
For more information, see Introduction to BigQuery INFORMATION_SCHEMA.
SELECT * FROM GV$SESSION;
SELECT * FROM V$ACTIVE_SESSION_HISTORY;
START TRANSACTION;
LOCK TABLE table_A IN EXCLUSIVE MODE NOWAIT;
DELETE FROM table_A;
INSERT INTO table_A SELECT * FROM table_B;
COMMIT;
Using a query:
bq query --replace --destination_table table_A 'SELECT * FROM table_B';
Using a copy:
bq cp -f table_A table_B
Both Oracle and BigQuery support transactions (sessions) and therefore support statements separated by semicolons that are consistently executed together. For more information, see Multi-statement transactions.
Oracle error codes and BigQuery error codes are different. If your application logic is currently catching the errors, try to eliminate the source of the error, because BigQuery doesn't return the same error codes.
Both Oracle and BigQuery are atomic—that is, ACID-compliant on a
per-mutation level across many rows. For example, a MERGE operation is
atomic, even with multiple inserted and updated values.
Oracle provides read committed or serializable transaction isolation levels. Deadlocks are possible. Oracle insert append jobs run independently.
BigQuery also
supports transactions.
BigQuery helps ensure
optimistic concurrency control
(first to commit wins) with
snapshot isolation,
in which a query reads the last committed data before the query starts. This
approach guarantees the same level of consistency on a per-row, per-mutation
basis and across rows within the same DML statement, yet avoids deadlocks. In
the case of multiple UPDATE statements against the same table, BigQuery
switches to
pessimistic concurrency control
and queues
multiple UPDATE statements, automatically retrying in case of conflicts. INSERT DML statements and
load jobs can run concurrently and independently to append to tables.
Oracle supports rollbacks. As there is no explicit transaction boundary in BigQuery, there
is no concept of an explicit rollback in BigQuery. The
workarounds are table decorators or
using FOR SYSTEM_TIME AS OF.
Check BigQuery latest quotas and limits. Many quotas for large-volume users can be raised by contacting the Cloud Customer Care. The following table shows a comparison of the Oracle and BigQuery database limits.
12 MB (maximum resolved legacy and GoogleSQL query length)
Streaming:
Other Oracle Database limits includes data type limits, physical database limits, logical database limits and process and runtime limits.
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-07-17 UTC.