Я использую Oracle 10g Express Edition с PHP codeigniter.
У меня есть таблица tbl_movie: –
CREATE TABLE tbl_movie (movie_id NUMBER(11) PRIMARY KEY, movie_title VARCHAR2(255) NOT NULL, movie_image VARCHAR2(255) NOT NULL, language_id NUMBER(11) NOT NULL REFERENCES tbl_language(language_id) ON DELETE CASCADE, showtime_id NUMBER(11) NOT NULL REFERENCES tbl_showtime(showtime_id) ON DELETE CASCADE, movie_sdate DATE NOT NULL, movie_edate DATE NOT NULL, movie_add_date DATE NOT NULL );
Теперь я создал процедуру, выполнив ее через Oracle Command Line:
CREATE OR REPLACE PROCEDURE insertMovie (id IN NUMBER, title IN VARCHAR2, image IN VARCHAR2, language IN NUMBER, showtime IN NUMBER, sdate IN DATE, edate IN DATE, adate IN DATE, message OUT NUMBER) IS BEGIN INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date) VALUES ( id, title, image, language, showtime, TO_DATE(sdate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(edate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(adate, 'YYYY-MM-DD hh24:mi:ss')); message := 1; EXCEPTION WHEN OTHERS THEN message := 0; END; /
Это код моего контроллера codeigniter:
public function testMovie() { $insertData['movie_id'] = 1; $insertData['movie_title']= 'test'; $insertData['movie_image']= 'rfgt'; $insertData['language_id']= 1; $insertData['showtime_id']= 1; $insertData['movie_sdate']= '2017-02-24 00:00:00'; $insertData['movie_edate']= '2017-02-27 00:00:00'; $insertData['movie_add_date']= '2017-02-20 00:00:00'; $this->load->model('oracle_model'); $return = $this->oracle_model->add_movie('movie',$insertData,''); }
И это функция модели, которая предназначена для вызова процедуры: –
function add_movie($entity,$insertData,$time) { print_r($insertData); $conn = oci_connect("xxxxxx", "xxxxxx","xxxxxxxxx"); if(!$conn) { echo "connect failed".oci_error(); } else { echo "connect done at".date('dm-y'); // calling stored procedure insertMovie $insertMovieProcedureSQL = "BEGIN insertMovie(:id, :title, :image, :language, :showtime, :sdate, :edate, :adate, :message); END;"; $stmt = oci_parse($conn, $insertMovieProcedureSQL); // Bind the input parameter oci_bind_by_name($stmt,':id',$insertData['movie_id']); oci_bind_by_name($stmt,':title',$insertData['movie_title']); oci_bind_by_name($stmt,':image',$insertData['movie_image']); oci_bind_by_name($stmt,':language',$insertData['language_id']); oci_bind_by_name($stmt,':showtime',$insertData['showtime_id']); oci_bind_by_name($stmt,':sdate',$insertData['movie_sdate']); oci_bind_by_name($stmt,':edate',$insertData['movie_edate']); oci_bind_by_name($stmt,':adate',$insertData['movie_add_date']); // Bind the output parameter oci_bind_by_name($stmt,':message',$message); oci_execute($stmt); // $message is now populated with the output value echo "$message\n"; } }
Когда я запускаю функцию, я получаю следующую ошибку:
oci_execute(): ORA-01861: literal does not match format string ORA-06512: at line 1
Когда я попытался запустить процедуру, исключив все столбцы типа даты, код работает нормально. Я думаю, что основная проблема связана с столбцами Date.
Но когда я запускаю этот запрос из командной строки, данные успешно вставлены: –
INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date) VALUES ( 2, 'title', 'image', 2, 3, TO_DATE('2017-02-24 00:00:00', 'YYYY-MM-DD hh24:mi:ss'), TO_DATE('2017-02-27 00:00:00', 'YYYY-MM-DD hh24:mi:ss'), TO_DATE('2017-02-20 00:00:00', 'YYYY-MM-DD hh24:mi:ss'));
Что я делаю не так? Я застрял почти 4 часа.
Параметры процедуры sdate
и т. Д. sdate
к типу данных DATE
. В рамках вашей процедуры вы применяете TO_DATE( ...., 'yyyy-mm-dd hh24:mi:ss')
к ним.
TO_DATE
используется для преобразования строк в даты, а не даты в даты. Если вы применяете TO_DATE
к дате, Oracle сначала преобразует дату в строку, чтобы ее можно было передать TO_DATE
. К сожалению, когда Oracle делает это неявное преобразование, он не использует ту же модель формата, что и в TO_DATE
; скорее, он использует nls_date_format
сеанса, который вызвал процедуру. Это не то же самое, что модель в TO_DATE
– что вызывает ошибку, которую вы видели.
Это можно решить двумя способами. Один из них – не использовать TO_DATE(sdate, ...)
а использовать только sdate
в INSERT
. sdate
а другие – это даты (если они были правильно приняты в качестве дат процедуры в первую очередь).
Во-вторых, если на самом деле вы имели в виду, что аргументы передаются как строки, не объявляйте их как DATE
в объявлении процедуры; объявите их VARCHAR2
. (И убедитесь, что эти строки верны в правильном формате – вы должны иметь возможность контролировать это из интерфейса.)
Всякий раз, когда вы видите TO_DATE(....)
примененную к входу DATE
, ожидайте ошибку, подобную той, которую вы видели. И наоборот, всякий раз, когда вы видите такую ошибку, подозрительный код, например TO_DATE(....)
применяется к дате.
Добавлено : есть и еще одна возможность. Если на самом деле вы передаете строки процедуре, Oracle должен преобразовать их в даты (потому что они объявлены как таковые). Если строки не совпадают в формате nls_date_format
сеанса, вызывающего процедуру, это первоначальное преобразование параметров из строк в даты не будет выполнено, и оператор INSERT
даже не будет достигнут.
Измените тип данных входных параметров с date
на varchar
. В текущем сценарии вы в основном применяете to_date
к типу данных date
. После того, как вы замените date
на varchar
, остальная часть логики должна работать.
CREATE OR REPLACE PROCEDURE insertMovie (id IN NUMBER, title IN VARCHAR2, image IN VARCHAR2, language IN NUMBER, showtime IN NUMBER, sdate IN VARCHAR2, edate IN VARCHAR2, adate IN VARCHAR2, message OUT NUMBER) IS BEGIN INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date) VALUES ( id, title, image, language, showtime, TO_DATE(sdate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(edate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(adate, 'YYYY-MM-DD hh24:mi:ss')); message := 1; EXCEPTION WHEN OTHERS THEN message := 0; END; /