Pls 00306 ошибочно число или типы аргументов при обращении к

PLS-00306: ошибочно число или типы аргументов при обращении к 'INSERTPRODUCT' Oracle Решение и ответ на вопрос 3001272

rus_el_di

1 / 1 / 0

Регистрация: 30.05.2021

Сообщений: 25

1

20.06.2022, 09:48. Показов 1843. Ответов 8

Метки нет (Все метки)


Всем добрый день.
Пытаюсь запустить процедуру, но выдает ошибку из темы

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--Создание процедуры добавления в таблицу Product  
CREATE OR REPLACE PROCEDURE INSERTproduct (
p_productid             IN          INT,
p_categoryid            IN          INT,
p_manufacturerid        IN          INT,
p_productstatusid       IN          INT,
p_name                  IN          varchar2, 
p_discription           IN          varchar2,
p_date_from             IN          DATE,
p_date_to               IN          DATE,
p_create_data           IN          DATE,
p_update_data           IN          DATE
)
IS
 
BEGIN
INSERT INTO product (product_id, category_id, manufacturer_id, product_status_id, name, discription, date_from, date_to, create_data, update_data)
VALUES (product_seq.NEXTVAL, 3, 6, 1, 'efefeegeg', 'syhyhyhys', '12-04-2020', NULL, sysdate, sysdate);
END INSERTproduct;
 
EXECUTE INSERTproduct

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



250 / 149 / 78

Регистрация: 12.04.2022

Сообщений: 617

20.06.2022, 09:52

2

1. DDL таблицы product .
2. Формат даты ’12-04-2020′ подозрительный!



0



rus_el_di

1 / 1 / 0

Регистрация: 30.05.2021

Сообщений: 25

20.06.2022, 09:57

 [ТС]

3

Цитата
Сообщение от PaulWist
Посмотреть сообщение

DDL таблицы product

SQL
1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE product --создание таблицы Продукт
(
    product_id                INT               NOT NULL, --уникальный id продукта
    category_id               INT               NOT NULL, --fk категорий
    manufacturer_id           INT               NOT NULL, --fk производителей
    product_status_id         INT               NOT NULL, --fk статуса продукта
    name                      varchar2 (100)     NOT NULL, --название продукта
    discription               varchar2 (100)    NOT NULL, --описание продукта
    date_from                 DATE              NOT NULL, --дата производства
    date_to                   DATE                  NULL, --дата просрочки
    create_data               DATE              NOT NULL, --дата создания
    update_data               DATE                  NULL, --дата для обновления данных

Цитата
Сообщение от PaulWist
Посмотреть сообщение

подозрительный!

Вбивал данные в таблицу по такому формату



0



PaulWist

250 / 149 / 78

Регистрация: 12.04.2022

Сообщений: 617

20.06.2022, 10:22

4

Попробуйте дату загнать так:

Oracle 11 SQL
1
TO_DATE('12-04-2022', 'dd-mm-yyyy')



0



1438 / 903 / 342

Регистрация: 31.05.2012

Сообщений: 3,169

20.06.2022, 11:01

5

а зачем параметры в процедуре коль не используются? и если они есть, то при обращении к процедуре нужно передать фактические значения параметров. у тебя же и сообщение об этом



0



1 / 1 / 0

Регистрация: 30.05.2021

Сообщений: 25

20.06.2022, 11:40

 [ТС]

6

Цитата
Сообщение от Аватар
Посмотреть сообщение

не используются

а какие параметры используются? как используются, зачем, у меня мозг ломается уже, 3 дня процедуру упрощаю, уже не понимаю что к чему соединяется



0



PaulWist

250 / 149 / 78

Регистрация: 12.04.2022

Сообщений: 617

20.06.2022, 12:10

7

Лучший ответ Сообщение было отмечено rus_el_di как решение

Решение

Цитата
Сообщение от rus_el_di
Посмотреть сообщение

а какие параметры используются?

На вход процедуре определены 10 параметров, при вызове exec их надо перечислить, либо создать процедуру без параметров, например:

Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
--Создание процедуры добавления в таблицу Product  
CREATE OR REPLACE PROCEDURE INSERTproduct 
IS
 
BEGIN
INSERT INTO product (product_id, category_id, manufacturer_id, product_status_id, name, discription, date_from, date_to, create_data, update_data)
VALUES (product_seq.NEXTVAL, 3, 6, 1, 'efefeegeg', 'syhyhyhys', '12-04-2020', NULL, SYSDATE, SYSDATE);
END INSERTproduct;
 
EXECUTE INSERTproduct



0



1 / 1 / 0

Регистрация: 30.05.2021

Сообщений: 25

20.06.2022, 13:13

 [ТС]

8

Цитата
Сообщение от PaulWist
Посмотреть сообщение

процедуре

хоть это и не решило мою проблему, так как мне сказали что, а если я захочу другие параметры ввести, но, меня очень удивило что можно сделать процедуру вот так без параметров и она выглядит очень просто и красиво, спасибо большое за советы



0



Модератор

4192 / 3031 / 577

Регистрация: 21.01.2011

Сообщений: 13,109

21.06.2022, 14:11

9

Цитата
Сообщение от rus_el_di
Посмотреть сообщение

Вбивал данные в таблицу по такому формату

Для сведения. Данные в поле date хранятся совсем не так, как ты вбиваешь или выводит на экран. Там хранятся числа, а на экран выводится с пом. функций преобразования (возможно по инициативе клиентской программы, например SQL Developer). Поэтому правильно использовать функции to_date и to_char, как было сказано выше. Иначе результат от NLS-установок сессии и тебе может повезти, а может нет



0



I know I’ve asked this online before, but is Tourette Syndrome an occupational hazard of being a programmer?  I swear, it’s things like this that are going to cause me to develop it.

I’ve just been through one of the more frustrating exercises, debugging database calls that look just fine.

Problem

Contents

  • Problem
  • Solution
  • Why This Is
    • Share this:

When calling Oracle PL/SQL stored procedures from C#, it appears many people get PLS-00306 responses with the message “wrong number or types of arguments  in call to ‘my_procedure’” (with the obvious substitution on procedure name).  I recently spent a few days trying to track down why this was happening in my program… intermittently.  Some reports worked, some didn’t.  I finally tracked the cause of the problem down, and it’s a subtle one unless you know about it already.

Oracle treats null strings and empty strings more or less interchangeably in most contexts.  You can’t compare the empty string to itself (” does not equal ”, but is null — in many RDBMS, the opposite is true, the empty string and the null string are distinctly different).  This is itself a gotcha that people usually learn the hard way.

The way this one bit me was pretty subtle, in that it’s really not obvious looking at the code how it fails.  I compared the parameter binding carefully, and all arguments were present with the correct types.

Let’s use a really simple example:

CREATE TABLE t (
  s  VARCHAR2(10)
);
 
CREATE OR REPLACE PROCEDURE myproc(
  in_s IN VARCHAR2
)
IS
BEGIN
  INSERT INTO t (s) VALUES (in_s);
END;

Nice and simple — a table with a single varchar2 field, and a procedure that inserts a new value into the table. Believe it or not, it’s really easy for this to break when called from C#.

Pretty much all documentation I’ve seen for calling Oracle stored procedures from C# involve setting up the connection (not shown here), creating an OracleCommand, binding the parameters, and executing the command.  Straightforward, but there’s a nonobvious gotcha in how it actually works.

A typical example might look something like this:

OracleConnection conn = new OracleConnection(connectString);
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "myproc";
OracleParameter op = new OracleParameter("in_s", OracleType.VarChar);
op.Value = "my value";
op.Direction = ParameterDirection.Input;
cmd.Parameters.Add(op);
cmd.ExecuteNonQuery();
cmd.Dispose();

This can be expected to work.  It would be really tedious to do every time (and more importantly, every place) you want to call myproc(), so it is likely to get wrapped in a method:

void CallMyProc(string s)
{
  OracleConnection conn = new OracleConnection(connectString);
  conn.Open();
  OracleCommand cmd = new OracleCommand();
  cmd.Connection = conn;
  cmd.CommandText = "myproc";
  OracleParameter op = new OracleParameter("in_s", OracleType.VarChar);
  op.Value = s;
  op.Direction = ParameterDirection.Input;
  cmd.Parameters.Add(op);
  cmd.ExecuteNonQuery();
  cmd.Dispose();
}

This is easy to call and works… as long as ‘s’ is not null. That is,

string s = "foo";
CallMyProc(s);

is just fine. No problem. For that matter,

string s = "";
CallMyProc(s);

also works.

However, and this is what has been chewing on me,

does not work, producing said ‘PLS-00306’ error. Compare the stored procedure to the C# invocation — the stored procedure takes a single argument, a varchar2 (‘string’), the single C# parameter is defined as expecting a varchar and something declared as string is bound. This should work, right?

Wrong. By the time the driver sees it, a not-empty-but-null string is not a string any more. Regardless of what C# says.

Solution

I’ll skip ahead to the solution, then come back for why this is.

void CallMyProc(string s)
{
  OracleConnection conn = new OracleConnection(connectString);
  conn.Open();
  OracleCommand cmd = new OracleCommand();
  cmd.Connection = conn;
  cmd.CommandText = "myproc";
  OracleParameter op = new OracleParameter("in_s", OracleType.VarChar);
  op.Value = String.IsNullOrEmpty(s) ? "" : s;
  op.Direction = ParameterDirection.Input;
  cmd.Parameters.Add(op);
  cmd.ExecuteNonQuery();
  cmd.Dispose();
}

It’s a simple change on line 9 and appears to have resolved the problem.

Why This Is

Figuring this out required a little bit of knowledge about how parameter binding and the execute immediate instruction work in Oracle.

Execute immediate with a bound parameter can look something like this:

EXECUTE IMMEDIATE 'begin myproc(:1); end;' using s;

This is just fine. However,

EXECUTE IMMEDIATE 'begin myproc(:1); end;' using NULL;

fails because null is typeless. Oracle cannot determine what type ‘:1’ is supposed to be and chokes (PLS-00457).

I’m not entirely sure how PLS-00457 becomes PLS-00306 here, but it seems related. When invoking an Oracle command from C#, it appears the runtime library is doing something close to

string dbcommand = "execute immediate 'begin " + command + "(" +
    /* build parameter list */ + "); end;' using " +
    /* build argument list */ + ";";

When one of the parameters has a null string value, this fails with a PLS-00306 error message. Using an empty string value instead (non-null C# string — has an address but no content) works just fine.

So, null and empty string are treated as the same thing (but not equal, oh no). Except when they aren’t.

How about that Tourette Syndrome? I’m sure I’m coming down with it.

Dealing with «PLS-306: Wrong number or types of arguments» across schemas

The PLS-306 compile error can be a real pain in the you know what. There are many possible causes, including typo in name with named notation, wrong datatype, wrong number of arguments….you know: just like the error message says. :-)

But one of the most puzzling situations occurs when you need to execute a subprogram that is defined in another schema of your instance, or in another instance entirely, and the type of at least one parameter in the subprogram is «user-defined» (not a built-in datatype).

So let’s first state the rule that should guide you in this scenario, and then I will offer up  some code so that you can verify it for yourself.

The rule:

Even if a user-defined type in one schema has the same name and same structure as a type in another schema, they are different types.

And now some code to drive the point home. Assuming you have two schemas defined, schema1 and schema2:

CONNECT schema1/schema1

CREATE OR REPLACE TYPE number_nt IS TABLE OF NUMBER

/

CREATE OR REPLACE PROCEDURE show_nt_count (n IN number_nt)

IS

BEGIN

   DBMS_OUTPUT.put_line (n.COUNT);

END;

/

GRANT EXECUTE ON show_nt_count TO schema2

/

GRANT EXECUTE ON number_nt TO schema2

/

And now I can successfully invoke show_nt_count from schema2 as follows:

CONNECT schema2/schema2

DECLARE

   n   schema1.number_nt := schema1.number_nt (1);

BEGIN

   schema1.show_nt_count (n);

END;

/

But that’s because I am defining a local variable based on the schema1 type.

If I try to use the «same» type that is defined in schema2, I get the PLS-00306 eorr:

CREATE OR REPLACE TYPE number_nt IS TABLE OF NUMBER

/

DECLARE

   n   number_nt := number_nt (1);

BEGIN

   schema1.show_nt_count (n);

END;

/

ORA-06550: line 4, column 1:

PLS-00306: wrong number or types of arguments in call to ‘PLCH_USE_N’

ORA-06550: line 4, column 1:

PL/SQL: Statement ignored

06550. 00000 —  «line %s, column %s:n%s»

*Cause:    Usually a PL/SQL compilation error.

This problem does not always occur with datatypes defined in built-in packages. For example, DBMS_SQL comes with several pre-defined collection types. If I use one of those with my two schemas, I will not get the PLS-00306 error:

CONNECT schema1/schema1

CREATE OR REPLACE PROCEDURE show_nt_count (

   n IN DBMS_SQL.number_table)

IS

BEGIN

   DBMS_OUTPUT.put_line (n.COUNT);

END;

/

GRANT EXECUTE ON show_nt_count TO schema2

/

CONNECT schema2/schema2

DECLARE

   n   DBMS_SQL.number_table;

BEGIN

   n(1) := 1;

   schema1.show_nt_count (n);

END;

/


Ah, but why don’t I get the error? As Kim Berg Hansen points out in the comments, it is not because there is any secret and mysterious action taken by the PL/SQL compiler («Built-in packages are special.»). Instead, it is because these are two schemas in the same instance, and each instance of the Oracle RDBMS has a single copy of DBMS_SQL defined in SYS.

In other words, both schema1 and schema2 are referencing the same type in the same package. So, of course, the compiler has nothing to complain about.

If, however, you try to do the same thing via a database link, the story changes (even if the database link ends up pointing to the same instance) . If I execute that last block, with the only change being to execute the schema1.show_nt_count as a remote stored procedure:

DECLARE
   n   DBMS_SQL.number_table;
BEGIN
   n(1) := 1;
   schema1.show_nt_count@my_db_link (n);
END;
/

Then I will get a PLS-00306 error, since the DBMS_SQL package referenced in my block can no longer be resolved by the compiler to be the same DBMS_SQL package in the now-remote schema1.

To get rid of this problem, I can force the resolution of DBMS_SQL in the above block to be the same as that used by the remote procedure call:


DECLARE
   n   DBMS_SQL.number_table@my_db_link;
BEGIN
   n(1) := 1;
   schema1.show_nt_count@my_db_link (n);
END;
/


And then no more PLS-00306 error!

Понравилась статья? Поделить с друзьями:
  • Plotting error non numeric vertex definition
  • Plotting error empty plot maple
  • Plotlink ошибка 13
  • Plotlink error 13
  • Plot error bars matplotlib