Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8112187
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T02:23:51+00:00 2026-06-06T02:23:51+00:00

Oracle’s PL/SQL is fairly new to me, so I need some help understanding if

  • 0

Oracle’s PL/SQL is fairly new to me, so I need some help understanding if the way I’m trying to use parameters in a Merge’s Using clause is even possible.

I’m working with Oracle 11g using ODP.NET for communication with an existing C# .NET 4.0 code-base that uses the SQL connection to retrieve/modify data. The existing SQL statement looks like so:

MERGE INTO Worker Target
USING
(
  SELECT
        :Id0            Id
       ,:Options0       Options
  FROM dual
  UNION ALL
  SELECT
        :Id1            Id
       ,:Options1       Options
  FROM dual
) Source
ON (Target.Id = Source.Id)
WHEN MATCHED THEN
  UPDATE SET
        Target.StateId = :StateId
       ,Target.Options = Source.Options

The Using clause is generated in a C# StringBuilder to accomodate a varying number of worker Id/Option pairs, while at the same time the matching parameters are created.

StringBuilder usingClause = new StringBuilder();
List<OracleParameter> parameters = new List<OracleParameter>();
for (int i = 0; i < workers.Count; ++i)
{
  if (i > 0)
    usingClause.Append("UNION ALL\n");
  usingClause.AppendFormat("SELECT\n   :Id{0}  Id\n  ,:Options{0}  Options\n FROM dual\n", i);

  parameters.Add(new OracleParameter("Id" + i, workers[i].Id));
  parameters.Add(new OracleParameter("Options" + i, workers[i].Options))
}
parameters.Add(new OracleParameter("StateId", pendingStateId));

The usingClause StringBuilder is combined with the rest of the Merge command into a string called ‘sql’, which is then used in an OracleCommand object. The C# to execute the SQL Merge statement looks like so:

OracleConnection cn = new OracleConnection(
  ConfigurationManager.ConnectionStrings["OracleSystemConnection"].ConnectionString
);

using (OracleCommand cmd = new OracleCommand(sql, cn))
{
  cmd.BindByName = true;
  cn.Open();
  foreach (OracleParameter prm in parameters)
    cmd.Parameters.Add(prm);

  cmd.ExecuteNonQuery();
  cn.Close();
}

I’ve tried it both with and without binding the parameters by name, and ensuring the order is correct when binding without the parameters by name. What I keep getting is an “ORA-01008: not all variables bound” error.

I’ve also tried running the Merge command in SQL Developer, and get a response of “Bind Variable ‘Id0’ is NOT DECLARED.” Usually when I run a command in SQL Developer with undeclared bind variables it opens a dialog to enter the values, but not with this SQL command, so it’s understandable that it would be undeclared in SQL Developer, but I don’t understand why this is the case with the ODP.NET/C# implementation, since I’m adding the parameters to the OracleCommand object.

If anyone could point out what I’m doing wrong, or tell me how to achieve the same effect, it would be greatly appreciated. Also, if anyone knows of a better way to pass a list of values into a Merge’s Using clause, than doing a bunch of SELECTs FROM dual with UNION ALLs between them, it would be appreciated as well.

Answer Using Long Raw for the Options Column

After a bit of work, this was the final solution. Thanks to tomi44g for pointing me in the right direction.

DECLARE
  TYPE id_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  TYPE option_array IS TABLE OF LONG RAW INDEX BY PLS_INTEGER;

  t_ids    id_array := :ids;
  t_options    option_array := :options;
BEGIN
  FORALL i IN 1..t.ids.count
    EXECUTE IMMEDIATE '
      MERGE INTO Worker Target
      USING (SELECT :1 Id, :2 Options FROM dual) Source
      ON (Source.Id = Target.Id)
      WHEN MATCHED THEN
      UPDATE SET
         Target.StateId = :3
        ,Target.Options = Source.Options' USING t_ids(i), t_options(i), :state_id;
END;

And this is what the C# changed to, to accomodate the solution.

// Gather the values into arrays for binding.
int[] workerIds = new int[workers.Count];
byte[][] workerOptions = new byte[workers.Count][];
BinaryFormatter binaryFormatter = new BinaryFormatter();
for (int i = 0; i < workers.Count; ++i)
{
    workerIds[i] = workers[i].Id;

    // There's an assumed limit of 4096 bytes here; this is just for testing
    MemoryStream memoryStream = new MemoryStream(4096);
    binaryFormatter.Serialize(memoryStream, workers[i].Options);
    workerOptions[i] = memoryStream.ToArray();
}


// Excute the command.
OracleConnection cn = new OracleConnection(
    ConfigurationManager.ConnectionStrings["OracleSystemConnection"].ConnectionString
);
using (OracleCommand cmd = new OracleCommand(sql, cn))
{
    cmd.BindByName = true;
    cn.Open();

    OracleParameter ids = new OracleParameter();
    ids.OracleDbType = OracleDbType.Int32;
    ids.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    ids.Value = workerIds;
    ids.ParameterName = "ids";

    OracleParameter options = new OracleParameter();
    options.OracleDbType = OracleDbType.LongRaw;
    options.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    options.Value = workerOptions;
    options.ParameterName = "options";

    cmd.Parameters.Add(ids);
    cmd.Parameters.Add(options);
    cmd.Parameters.Add(new OracleParameter("state_id", pendingStateId));

    try
    {
        cmd.ExecuteNonQuery();
    }
    catch (OracleException e)
    {
        foreach (OracleError err in e.Errors)
        {
            Console.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
            System.Diagnostics.Debug.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
        }
    }
    cn.Close();
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T02:23:53+00:00Added an answer on June 6, 2026 at 2:23 am

    You would be better off binding the list of ids and options to arrays and then execute MERGE using FORALL in PL/SQL block:

    DECLARE
      TYPE id_array_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
      TYPE options_array_type IS TABLE OF VARCHAR2 (100) INDEX BY PLS_INTEGER;
    
      t_ids        id_array_type := :ids;
      t_options    options_array_type  := :options;
      v_state_id   NUMBER := :stateId;
    BEGIN
      FORALL i IN 1 .. t_ids.count
        EXECUTE IMMEDIATE '
          MERGE INTO worker target
          USING (SELECT :id id, :options options FROM dual) source
          ON (source.id = target.id)
          WHEN MATCHED THEN UPDATE SET target.stateId = :state_id, target.options = source.options'
          USING t_ids (i), t_options (i), v_state_id;
    END;
    

    Then you can bind the parameter as PL/SQL Associative Array
    Doing this you will have always one SQL statement in SGA rather than many statements for all possible number of parameters and (which is probably more important) you will be able to merge 1000s of elements in one go.

    Actually, I noticed that you are not using the WHEN NOT MATCHED clause. If you are genuinely not interested in inserting new records then there is no need to use MERGE at all, use simply UPDATE instead. You can efficiently execute an UPDATE statement multiple times in one round trip using Array Binding.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Oracle SQL can do hierarchical queries since v2, using their proprietary CONNECT BY syntax.
Oracle'c COLLECT function triggers creation of a new collection type. Is there a way
Oracle version : 10g I'm trying to use the MIN function to find the
Oracle 10g has Profiles that allow various resources to be limited. Here are some
Oracle JDBC connection with Weblogic 10 datasource mapping, giving problem java.sql.SQLException: Closed Connection I
Oracle Application server 10g I need to run the long running reports in the
On Oracle 10g we need to insert records from a view into a table
Using Oracle, how can I find index names and creation dates from systables/information_schema? How
In Oracle you can use &&VAR_NAME in a script and then the script will
oracle sql: select trunc( sysdate, 'Month') month from dual java: java.sql.Date sqlDate = resultSet.getDate(month);

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.