Ora

What is the difference between @@ and @ in Sqlplus?

Published in SQLPlus Scripting 5 mins read

In SQL*Plus, both @ and @@ are used to execute SQL scripts, but their primary distinction lies in how they resolve the file path of the script, particularly when dealing with nested scripts.

SQL*Plus provides powerful capabilities for interacting with an Oracle database, and a fundamental feature is the ability to execute external SQL scripts. The @ and @@ commands serve this purpose, allowing users to modularize their SQL code.

The fundamental difference between @ and @@ lies in their approach to resolving the script's path:

@ (Single At Sign)

When you use @, SQL*Plus attempts to locate the script based on one of the following:

  • Current Working Directory: If a relative path is provided (e.g., @my_script.sql), SQLPlus searches for the script relative to the current working directory from which the SQLPlus session was launched.
  • SQLPATH Environment Variable: SQL*Plus also checks directories specified in the SQLPATH environment variable.
  • Absolute Paths: You can provide an absolute path to the script (e.g., @/path/to/my_script.sql), making its location explicit regardless of the current working directory or SQLPATH.

Example: If you launch SQLPlus from /home/user and execute @scripts/report.sql, SQLPlus looks for report.sql in /home/user/scripts/. If you then run @/tmp/data_load.sql, it executes the script from /tmp/data_load.sql.

@@ (Double At Sign)

The @@ command is specifically designed for executing nested scripts within a larger script structure. Its key characteristic is that it resolves the path of the script relative to the directory of the currently running (calling) script.

  • Contextual Path Resolution: This means if script A calls script B using @@, SQLPlus will look for script B in a path relative to script A's location, not the current working directory of the SQLPlus session.
  • Use Case: This behavior is extremely useful for building modular SQL*Plus applications where a main script calls several sub-scripts located in the same directory or a subdirectory relative to the main script. It allows you to move a set of related scripts without breaking their internal references.

Example:
Imagine you have a main script main_app.sql located in /project/sql_modules/. Inside main_app.sql, it calls a sub-script using @@setup/init.sql. SQLPlus will look for init.sql in /project/sql_modules/setup/, because main_app.sql is located in /project/sql_modules/. This happens regardless of the directory from which you initially launched your SQLPlus session (e.g., if you launched SQL*Plus from /tmp and then ran @/project/sql_modules/main_app.sql).

Practical Implications and Use Cases

The choice between @ and @@ significantly impacts script portability and modularity:

  • Modular Scripting: @@ is indispensable for creating robust, modular SQLPlus applications. You can define a main script that calls various component scripts, and as long as those component scripts are located relative to the main script, the @@ command will always find them, regardless of where SQLPlus was initially launched.
  • Portability: Scripts using @@ are more portable. You can copy an entire script hierarchy to a different location on the file system, and as long as the relative paths within the scripts remain valid, they will execute correctly.
  • Avoiding CD Commands: Without @@, you might frequently need to use CD (change directory) commands within your scripts or manually navigate to the correct directory before executing nested scripts with @. @@ eliminates this necessity, streamlining script execution.

Comparison Table

Feature @ (Single At Sign) @@ (Double At Sign)
Path Resolution Relative to current working directory or SQLPATH. Can use absolute paths. Relative to the directory of the calling script.
Primary Use Case Executing top-level scripts; scripts with absolute paths; simple calls. Executing nested scripts within a modular application.
Portability Less portable for relative paths; depends on SQL*Plus launch directory. Highly portable; independent of SQL*Plus launch directory.
Modularity Can be cumbersome for deeply nested or complex structures. Ideal for managing complex, hierarchical script structures.
Context Current working directory of the SQL*Plus session. Directory of the script that contains the @@ command.

When to Use Which

  • Use @ when:
    • Executing a standalone script directly from the command line or from an absolute path.
    • You are certain of the current working directory of your SQL*Plus session.
    • The script does not call other scripts, or if it does, those are also referred to by absolute paths or are discoverable via SQLPATH.
  • Use @@ when:
    • You have a main script that calls several sub-scripts, and those sub-scripts are located relative to the main script's directory.
    • Building modular, multi-file SQL*Plus applications that need to be robust and portable across different execution environments.
    • You want to avoid issues with current working directories when executing nested scripts.

Example Illustrating the Difference

Consider the following directory structure:

/project/
├── main.sql
└── config/
    └── setup_env.sql
  1. Scenario: Using @ for a nested call

    • You launch SQL*Plus from /tmp.
    • You execute @/project/main.sql.
    • Inside main.sql, you have the line: @config/setup_env.sql
    • Result: main.sql executes. However, when it tries to run @config/setup_env.sql, SQLPlus will search for /tmp/config/setup_env.sql (relative to the current working directory* /tmp), leading to an error because the file isn't there.
  2. Scenario: Using @@ for a nested call

    • You launch SQL*Plus from /tmp.
    • You execute @/project/main.sql.
    • Inside main.sql, you have the line: @@config/setup_env.sql
    • Result: main.sql executes. When it tries to run @@config/setup_env.sql, SQLPlus will search for /project/config/setup_env.sql (relative to the directory of the calling script*, main.sql, which is in /project/), and setup_env.sql will be found and executed correctly.

This demonstrates how @@ provides a much more robust and predictable way to handle nested script execution, especially in complex project structures or shared environments where the initial launch directory of SQL*Plus might vary.