cancel
Showing results for 
Search instead for 
Did you mean: 
Data Engineering
Join discussions on data engineering best practices, architectures, and optimization strategies within the Databricks Community. Exchange insights and solutions with fellow data engineers.
cancel
Showing results for 
Search instead for 
Did you mean: 

Calling stored procs using identifier function

hobrob_ex
New Contributor III

hi folks

I'm hitting an error when trying to call a stored procedure using the identifier function, potentially looks like it could be a bug.

Calling the proc with a normal reference as follows works just fine.

`call my_catalog.my_schema.my_proc('2026-01-01');`

As soon as I try to use the identifier function so I can use variables to point at different procedure versions for a procedure I get the error further below.

`call identifier('my_catalog.my_schema.my_proc')('2026-01-01');`

'PlanWithUnresolvedIdentifier my_catalog.my_schema.my_proc, org.apache.spark.sql.catalyst.parser.AstBuilder$$Lambda$29635/0x00007f56d3f7d8d8@340ce335 (of class org.apache.spark.sql.catalyst.analysis.PlanWithUnresolvedIdentifier)

   I only get this problem with stored procedures, using identifier() for tables, views etc doesn't yield any errors.   

1 ACCEPTED SOLUTION

Accepted Solutions

szymon_dybczak
Esteemed Contributor III

Hi @hobrob_ex ,

This is expected behavior. According to documentation  IDENTIFIER clause is limited to the following statements:

"The table, view, or function subject name of a CREATE, ALTER, DROP, or UNDROP statement.

The target table name of a MERGE, UPDATE, DELETE, INSERT, COPY INTO statements.

The target of a SHOW or DESCRIBE statement.

USE of a schema or catalog

A function invocation

A column, table or view referenced in a query. This includes queries embedded in a DDL or DML statement."

View solution in original post

4 REPLIES 4

szymon_dybczak
Esteemed Contributor III

Hi @hobrob_ex ,

This is expected behavior. According to documentation  IDENTIFIER clause is limited to the following statements:

"The table, view, or function subject name of a CREATE, ALTER, DROP, or UNDROP statement.

The target table name of a MERGE, UPDATE, DELETE, INSERT, COPY INTO statements.

The target of a SHOW or DESCRIBE statement.

USE of a schema or catalog

A function invocation

A column, table or view referenced in a query. This includes queries embedded in a DDL or DML statement."

hobrob_ex
New Contributor III

Ah that's a shame, I don't suppose you know whether CALL would be supported in the future? I think I can work around it by using EXECUTE IMMEDIATE instead but IDENTIFIER would be cleaner.

szymon_dybczak
Esteemed Contributor III

Unfortunately, I don't know. But good idea with using Execute Immediate as a workaround 🙂

SteveOstrowski
Databricks Employee
Databricks Employee

Hi @hobrob_ex,

The IDENTIFIER() clause does not currently support the CALL statement for stored procedures. The IDENTIFIER clause documentation lists its supported contexts: DDL operations (CREATE, ALTER, DROP, UNDROP), DML operations (MERGE, UPDATE, DELETE, INSERT, COPY INTO), query operations (SELECT), SHOW/DESCRIBE, and function invocations in expressions. CALL is not among them, which is why you are seeing the PlanWithUnresolvedIdentifier error.

This is consistent with what you observed: IDENTIFIER() works for tables, views, and functions in SELECT/DDL contexts, but not for procedure names in CALL.

WORKAROUND: EXECUTE IMMEDIATE

You can use EXECUTE IMMEDIATE to dynamically construct and run a CALL statement. This lets you parameterize the procedure name while keeping things SQL-injection safe with proper variable handling.

Option 1: Build the full CALL string dynamically

DECLARE proc_name STRING DEFAULT 'my_catalog.my_schema.my_proc';
DECLARE call_sql STRING;
SET call_sql = 'CALL ' || proc_name || '(\'2026-01-01\')';
EXECUTE IMMEDIATE call_sql;

Option 2: Use parameter markers for the procedure arguments (keeps the argument values parameterized, though the procedure name itself is still concatenated)

DECLARE proc_name STRING DEFAULT 'my_catalog.my_schema.my_proc';
DECLARE call_sql STRING;
DECLARE run_date STRING DEFAULT '2026-01-01';
SET call_sql = 'CALL ' || proc_name || '(:dt)';
EXECUTE IMMEDIATE call_sql USING run_date AS dt;

Option 3: If you are doing this from a notebook with Python/Scala, you can also use string formatting to build the SQL

catalog = "my_catalog"
schema = "my_schema"
proc = "my_proc"
run_date = "2026-01-01"
spark.sql(f"CALL {catalog}.{schema}.{proc}('{run_date}')")

DOCUMENTATION REFERENCES

IDENTIFIER clause (supported statements):
https://docs.databricks.com/en/sql/language-manual/sql-ref-names-identifier-clause.html

EXECUTE IMMEDIATE:
https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-aux-execute-immediate.html

CALL statement:
https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-aux-call.html

* This reply used an agent system I built to research and draft this response based on the wide set of documentation I have available and previous memory. I personally review the draft for any obvious issues and for monitoring system reliability and update it when I detect any drift, but there is still a small chance that something is inaccurate, especially if you are experimenting with brand new features.

If this answer resolves your question, could you mark it as "Accept as Solution"? That helps other users quickly find the correct fix.