Error report - SQL Error: ORA-01843: not a valid month 01843 - oracle-sqldeveloper

I am using sql developer for the first time. I cant understand why this error is occuring.
CREATE TABLE TOY_STORE
( TOY_STORE_ID NUMBER(3,0),
TOY_STORE_NAME VARCHAR2(30 BYTE) NOT NULL ENABLE,
CITY VARCHAR2(30 BYTE) DEFAULT 'DELHI',
PHONENUMBER" NUMBER(10,0) NOT NULL ENABLE,
STORE_OPENING_TIME TIMESTAMP (6),
STORE_CLOSING_TIME TIMESTAMP (6),
CHECK (EXTRACT(HOUR FROM CAST (TO_CHAR (STORE_OPENING_TIME, 'YYYY-MON-DD HH24:MI:SS') AS TIMESTAMP)) > 8 || NULL),
CHECK (EXTRACT(HOUR FROM CAST (TO_CHAR (STORE_CLOSING_TIME, 'YYYY-MON-DD HH24:MI:SS') AS TIMESTAMP)) < 21 || NULL);
INSERT INTO TOY_STORE
VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312, '2014-04-01 09:10:12', '2014-04-01 21:42:05');
Following was the error given:
Error report - SQL Error: ORA-01843: not a valid month 01843. 00000 - "not a valid month" *Cause: *Action: Error starting at line : 1 in command - INSERT INTO TOY_STORE VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312, '04-2014-04 09:10:12', '04-2014-04 21:42:05') Error report - SQL Error: ORA-01843: not a valid month 01843. 00000 - "not a valid month"

Your create table as shown in the question has a stray double-quote and is missing a closing parenthesis. Your check constraints are odd:
you are converting a timestamp to a string using a specific format, and then casting back to a timestamp using the session NLS_TIMESTAMP_FORMAT, which will fail for sessions which don't have the setting you expect;
your are concatenating a null onto the hour value you're checking for, e.g. 21 || NULL, which is converting it to a string. Pretty sure you want to allow that to be null so you're using || as or, which isn't correct; but you don't need to explicitly allow for that anyway.
CREATE TABLE TOY_STORE (
TOY_STORE_ID NUMBER(3,0),
TOY_STORE_NAME VARCHAR2(30 BYTE) NOT NULL ENABLE,
CITY VARCHAR2(30 BYTE) DEFAULT 'DELHI',
PHONENUMBER NUMBER(10,0) NOT NULL ENABLE,
STORE_OPENING_TIME TIMESTAMP (6),
STORE_CLOSING_TIME TIMESTAMP (6),
CHECK (EXTRACT(HOUR FROM STORE_OPENING_TIME) > 8),
CHECK (EXTRACT(HOUR FROM STORE_CLOSING_TIME) < 21)
);
You might want to consider naming your constraints; and you might want a lower bound on the closing time and an upper bound on the opening time, or at least make sure opening isn't after closing (unless you're allowing for night opening; in which case you probably wouldn't want those constraints at all).
Then you are inserting using a string literal, not a timestamp. You are again relying on implicit conversion using your client's NLS_TIMESTAMP_FORMAT setting. The SQL Developer default for that is DD-MON-RR HH24.MI.SSXFF, which means with `'2014-04-01 09:10:12`` it will try to map the parts of the string literal to the parts of the format mask and fail; that default model does give ORA-01843.
You should either convert your string with an explicit format mask, using to_timestamp():
INSERT INTO TOY_STORE (TOY_STORE_ID, TOY_STORE_NAME, CITY, PHONENUMBER,
STORE_OPENING_TIME, STORE_CLOSING_TIME)
VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312,
to_timestamp('2014-04-01 09:10:12', 'YYYY-MM-DD HH24:MI:SS'),
to_timestamp('2014-04-01 21:42:05', 'YYYY-MM-DD HH24:MI:SS'));
or use ANSI timestamp literals:
INSERT INTO TOY_STORE (TOY_STORE_ID, TOY_STORE_NAME, CITY, PHONENUMBER,
STORE_OPENING_TIME, STORE_CLOSING_TIME)
VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312,
timestamp '2014-04-01 09:10:12', timestamp '2014-04-01 21:42:05');
... which violates your constraint as expected:
SQL Error: ORA-02290: check constraint (SCHEMA.SYS_C00113492) violated
02290. 00000 - "check constraint (%s.%s) violated"
*Cause: The values being inserted do not satisfy the named check
*Action: do not insert values that violate the constraint.
Notice the SYS_C00113492 name; that's a system-generated name for your constraint. It will be easier to follow what is happening if you name your constraints.
You are still allowed to insert nulls:
INSERT INTO TOY_STORE (TOY_STORE_ID, TOY_STORE_NAME, CITY, PHONENUMBER,
STORE_OPENING_TIME, STORE_CLOSING_TIME)
VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312, null, null);
1 row inserted.

Related

Error Fixed Length column [MyColumn] data length mismatch in ORACLE

I have an error when doing:
FDTable.Refresh;
The error is the following:
"Fixed Length column [COL3] data length mismatch. Value length - [34], column fixed length - [4]"
The above error does not always occur, and sometimes the problem is removed when I rename the table in ORACLE (RENAME TABLE ..) to any other name.
My table is like the following:
CREATE TABLE "MyDB"."TABLE_A"(
COL1 VARCHAR2(1 CHAR) DEFAULT(' ') COLLATE USING_NLS_COMP NOT NULL ENABLE,
COL2 NUMBER(10, 0) NOT NULL ENABLE,
COL3 NUMBER(10, 0) NOT NULL ENABLE
//other columns
CONSTRAINT TABLE_A1 PRIMARY KEY (COL1, COL2, COL3)
) DEFAULT COLLATION USING_NLS_COMP
I have the following "Map Rule":
with MapRules.Add do begin
PrecMin:= 10;
PrecMax:= 10;
ScaleMin:= 0;
ScaleMax:= 0;
SourceDataType:= dtBCD;
SourceDataType:= dtInt32;
end;
I have observed in "TFDPhysOracleCommand.CreateDefineInfo", that when I activate (TFDTable.Active:= True), the value of the precision of this column is 10, however, when it fails, the value that is taken in the precision (variable " iPrec") is equal to 38.
Information:
Oracle 12c R2.
RAD Studio XE7.
Any suggestion?
Thanks in advance.

Column is of type timestamp without time zone but expression is of type character

I'm trying to insert records on my trying to implement an SCD2 on Redshift
but get an error.
The target table's DDL is
CREATE TABLE ditemp.ts_scd2_test (
id INT
,md5 CHAR(32)
,record_id BIGINT IDENTITY
,from_timestamp TIMESTAMP
,to_timestamp TIMESTAMP
,file_id BIGINT
,party_id BIGINT
)
This is the insert statement:
INSERT
INTO ditemp.TS_SCD2_TEST(id, md5, from_timestamp, to_timestamp)
SELECT TS_SCD2_TEST_STAGING.id
,TS_SCD2_TEST_STAGING.md5
,from_timestamp
,to_timestamp
FROM (
SELECT '20150901 16:34:02' AS from_timestamp
,CASE
WHEN last_record IS NULL
THEN '20150901 16:34:02'
ELSE '39991231 11:11:11.000'
END AS to_timestamp
,CASE
WHEN rownum != 1
AND atom.id IS NOT NULL
THEN 1
WHEN atom.id IS NULL
THEN 1
ELSE 0
END AS transfer
,stage.*
FROM (
SELECT id
FROM ditemp.TS_SCD2_TEST_STAGING
WHERE file_id = 2
GROUP BY id
HAVING count(*) > 1
) AS scd2_count_ge_1
INNER JOIN (
SELECT row_number() OVER (
PARTITION BY id ORDER BY record_id
) AS rownum
,stage.*
FROM ditemp.TS_SCD2_TEST_STAGING AS stage
WHERE file_id IN (2)
) AS stage
ON (scd2_count_ge_1.id = stage.id)
LEFT JOIN (
SELECT max(rownum) AS last_record
,id
FROM (
SELECT row_number() OVER (
PARTITION BY id ORDER BY record_id
) AS rownum
,stage.*
FROM ditemp.TS_SCD2_TEST_STAGING AS stage
)
GROUP BY id
) AS last_record
ON (
stage.id = last_record.id
AND stage.rownum = last_record.last_record
)
LEFT JOIN ditemp.TS_SCD2_TEST AS atom
ON (
stage.id = atom.id
AND stage.md5 = atom.md5
AND atom.to_timestamp > '20150901 16:34:02'
)
) AS TS_SCD2_TEST_STAGING
WHERE transfer = 1
and to short things up, I am trying to insert 20150901 16:34:02 to from_timestamp and 39991231 11:11:11.000 to to_timestamp.
and get
ERROR: 42804: column "from_timestamp" is of type timestamp without time zone but expression is of type character varying
Can anyone please suggest how to solve this issue?
Postgres isn't recognizing 20150901 16:34:02 (your input) as a valid time/date format, so it assumes it's a string.
Use a standard date format instead, preferably ISO-8601. 2015-09-01T16:34:02
SQLFiddle example
Just in case someone ends up here trying to insert into a postgresql a timestamp or a timestampz from a variable in groovy or Java from a prepared statement and getting the same error (as I did), I managed to do it by setting the property stringtype to "unspecified". According to the documentation:
Specify the type to use when binding PreparedStatement parameters set
via setString(). If stringtype is set to VARCHAR (the default), such
parameters will be sent to the server as varchar parameters. If
stringtype is set to unspecified, parameters will be sent to the
server as untyped values, and the server will attempt to infer an
appropriate type. This is useful if you have an existing application
that uses setString() to set parameters that are actually some other
type, such as integers, and you are unable to change the application
to use an appropriate method such as setInt().
Properties props = [user : "user", password: "password",
driver:"org.postgresql.Driver", stringtype:"unspecified"]
def sql = Sql.newInstance("url", props)
With this property set, you can insert a timestamp as a string variable without the error raised in the question title. For instance:
String myTimestamp= Instant.now().toString()
sql.execute("""INSERT INTO MyTable (MyTimestamp) VALUES (?)""",
[myTimestamp.toString()]
This way, the type of the timestamp (from a String) is inferred correctly by postgresql. I hope this helps.
Inside apache-tomcat-9.0.7/conf/server.xml
Add "?stringtype=unspecified" to the end of url address.
For example:
<GlobalNamingResources>
<Resource name="jdbc/??" auth="Container" type="javax.sql.DataSource"
...
url="jdbc:postgresql://127.0.0.1:5432/Local_DB?stringtype=unspecified"/>
</GlobalNamingResources>

Number of columns or their types differ between the queries

Using PostgreSQL 9.4.3 on Debian Jessie 64.
question.sql :
\set client_min_messages = debug
BEGIN;
SELECT * from no_plan();
SELECT Dugong.Users_Add('Sarit','thisispassword','programmer');
SELECT is(Dugong.Users_isExist('Sarit'),'t', 'Test Question_isExist() should return true' );
PREPARE A AS SELECT Username, Password, Privilege FROM Dugong.Users;
SELECT results_eq('A',$$VALUES ('sarit','thisispassword','programmer') $$,'Test wtf');
SELECT results_eq('A',$$VALUES ('Sarit','thisispassword','programmer') $$,'Test wtf');
SELECT * FROM finish();
ROLLBACK;
Output:
postgres#jaikra:/home/sarit/4alls/anemonesfish/pgtap$ pg_prove -v -d skorplusdb question.sql
question.sql ..
Sarit
ok 1 - Test Question_isExist() should return true
not ok 2 - Test wtf
# Failed test 2: "Test wtf"
# Number of columns or their types differ between the queries:
# have: (Sarit,thisispassword,programmer)
# want: (sarit,thisispassword,programmer)
not ok 3 - Test wtf
# Failed test 3: "Test wtf"
# Number of columns or their types differ between the queries
1..3
# Looks like you failed 2 tests of 3
Failed 2/3 subtests
Test Summary Report
-------------------
question.sql (Wstat: 0 Tests: 3 Failed: 2)
Failed tests: 2-3
Files=1, Tests=3, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.03 cusr 0.00 csys = 0.05 CPU)
Result: FAIL
Table:
CREATE TABLE Dugong.Users
( Username varchar(255),
Password varchar(255) NOT NULL,
Privilege varchar(255),
FirstName varchar(255),
MiddleName varchar(255),
LastName varchar(255),
StreetAddr varchar(255),
Subdistrict varchar(255),
District varchar(255),
Province varchar(255),
Country varchar(255),
Zipcode varchar(255),
Email varchar(255),
PhoneCountryCode varchar(10),
PhoneAreaCode varchar(255),
PhoneNum varchar(255),
FaxCountryCode varchar(255),
FaxAreaCode varchar(255),
FaxNum varchar(255),
LastModified timestamp with time zone default current_timestamp,
PRIMARY KEY(UserName)
);
Updates
Goal: To test my Users_Add function. Is it hold all the values I gave.
Expect: Table Users has 1 record with 3 values.
My attempt:
On 2nd error. It shows me 3 columns. That is a good response. Since I intentionaly make it wrong. So in the near future I will let it be a correct one.
However, 3rd error is strange. I copy and change 2nd case to be what I want, let it be uppercase on 'S'. Then prepared query has 3 columns and I check 3 values.
I have another overload function that INSERT INTO all 20 columns. Right now I want only 3. After got the error I go back to document.
Refer to document error, it says query and values have different column count. But it is not my case.
Problem:
My query has 3 columns and I let pgtap check only 3 columns, but 3rd case raises that I am letting it check unequal columns size of record.
Any information about my installation please ask. I will provide them to you as fast as I can.
Probably the number of columns is not a problem, but rather their types. Try this:
SELECT results_eq('A',
$$VALUES (
'sarit'::varchar(255),
'thisispassword'::varchar(255),
'programmer'::varchar(255)) $$,
'Test wtf');
SELECT results_eq('A',
$$VALUES (
'Sarit'::varchar(255),
'thisispassword'::varchar(255),
'programmer'::varchar(255)) $$,
'Test wtf');
The problem stems from the fact that the default type for a string (like 'sarit') istext. Generally, using varchar(n) is rather inconvenient when compared to text.
More on this topic can be found here: Any downsides of using data type "text" for storing strings? and PostgreSQL: Difference between text and varchar (character varying).

Convert a string representing a timestamp to an actual timestamp in PostgreSQL?

In PostgreSQL: I convert string to timestamp with to_timestamp():
select * from ms_secondaryhealthcarearea
where to_timestamp((COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS')
> to_timestamp('20121128191843','YYYYMMDDHH24MISS')
But I get this error:
ERROR: syntax error at end of input
LINE 1: ...H24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
^
********** Error **********
ERROR: syntax error at end of input
SQL state: 42601
Character: 176
Why? How to convert a string to timestamp?
One too many opening brackets. Try this:
select *
from ms_secondaryhealthcarearea
where to_timestamp(COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
You had two opening brackets at to_timestamp:
where to_timestamp((COA.. -- <-- the second one is not needed!
#ppeterka has pointed out the syntax error.
The more pressing question is: Why store timestamp data as string to begin with? If your circumstances allow, consider converting the column to its proper type:
ALTER TABLE ms_secondaryhealthcarearea
ALTER COLUMN update_datetime TYPE timestamp
USING to_timestamp(update_datetime,'YYYYMMDDHH24MISS');
Or use timestamptz - depending on your requirements.
Another way to convert a string to a timestamp type of PostgreSql is the above,
SELECT to_timestamp('23-11-1986 06:30:00', 'DD-MM-YYYY hh24:mi:ss')::timestamp without time zone;
I had the same requirement as how I read the title. How to convert an epoch timestamp as text to a real timestamp. In my case I extracted one from a json object. So I ended up with a timestamp as text with milliseconds
'1528446110978' (GMT: Friday, June 8, 2018 8:21:50.978 AM)
This is what I tried. Just the latter (ts_ok_with_ms) is exactly right.
SELECT
data->>'expiration' AS expiration,
pg_typeof(data->>'expiration'),
-- to_timestamp(data->>'expiration'), < ERROR: function to_timestamp(text) does not exist
to_timestamp(
(data->>'expiration')::int8
) AS ts_wrong,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) AS ts_ok,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) + (
CASE
WHEN LENGTH(data->>'expiration') = 13
THEN RIGHT(data->>'expiration', 3) ELSE '0'
END||' ms')::interval AS ts_ok_with_ms
FROM (
SELECT '{"expiration": 1528446110978}'::json AS data
) dummy
This is the (transposed) record that is returned:
expiration 1528446110978
pg_typeof text
ts_wrong 50404-07-12 12:09:37.999872+00
ts_ok 2018-06-08 08:21:50+00
ts_ok_with_ms 2018-06-08 08:21:50.978+00
I'm sure I overlooked a simpler version of how to get from a timestamp string in a json object to a real timestamp with ms (ts_ok_with_ms), but I hope this helps nonetheless.
Update: Here's a function for your convenience.
CREATE OR REPLACE FUNCTION data.timestamp_from_text(ts text)
RETURNS timestamptz
LANGUAGE SQL AS
$$
SELECT to_timestamp(LEFT(ts, 10)::int8) +
(
CASE
WHEN LENGTH(ts) = 13
THEN RIGHT(ts, 3) ELSE '0'
END||' ms'
)::interval
$$;

ORA-00917: missing comma

Name Null Type
------------------ -------- --------------
RESOURCE_ID NOT NULL NUMBER(38)
RESOURCE_FIRST_NM NOT NULL VARCHAR2(30)
RESOURCE_MIDDLE_NM VARCHAR2(30)
RESOURCE_LAST_NM NOT NULL VARCHAR2(30)
RESOURCE_TYPE_CD NOT NULL VARCHAR2(10)
EMPLOYEE_ID VARCHAR2(20)
EMPLOYEE_TYPE_CD VARCHAR2(10)
FUNCTIONAL_LEAD_CD VARCHAR2(10)
PHONE_1 VARCHAR2(15)
PHONE_2 VARCHAR2(15)
FAX_NR VARCHAR2(15)
EMAIL_DE VARCHAR2(50)
RESOURCE_STATUS_CD NOT NULL VARCHAR2(10)
HIRING_DT NOT NULL DATE
LEAVE_START_DT DATE
LEAVE_END_DT DATE
TERMINATED_DT DATE
ADDRESS1 VARCHAR2(50)
ADDRESS2 VARCHAR2(50)
CITY VARCHAR2(15)
STATE VARCHAR2(15)
int i=statement.executeUpdate("
insert into RAS_T_RESOURCES(
RESOURCE_ID,
RESOURCE_FIRST_NM,
RESOURCE_MIDDLE_NM,
RESOURCE_LAST_NM,
RESOURCE_TYPE_CD,
EMPLOYEE_ID,
FUNCTIONAL_LEAD_CD,
ADDRESS1,
ADDRESS2,
PHONE_1,
PHONE_2,
FAX_NR,
EMAIL_DE,
RESOURCE_STATUS_CD,
HIRING_DT,
LEAVE_START_DT,
LEAVE_END_DT,
TERMINATED_DT,
CITY,
STATE)
values(
2,
'"+strFirstname+"',
'"+strMiddlename+"',
'"+strLastname+"',
'"+strResourceType+"',
'"+strEmpId+"',
'"+strHiringMngr+"',
'"+strAddress1+"',
'"+strAddress2+"',
'"+strPhone1+"',
'"+strPhone2+"',
'"+strFax+"',
'"+strEMail+"',
'"+strstatus+"',
"+strHiringDate+",
"+strStartDate+",
"+strEndDate+",
"+strTerminatedDate+",
'"+strCity+"',
'"+strState+"');");
Can any one help? What is the problem?
My guess is that the problem is that you're not using bind variables and that you're getting an error related to concatenating a string. If there are commas in the data, for example, that will cause problems. Any of the Oracle DATE columns will generate issues if the Java string happens not to match the session's NLS_DATE_FORMAT.
For performance, usability, and security reasons, I'd strongly suggest using bind variables instead.
Thinking purely as a compiler, expressions like this:
'"+strFirstname+"'
would be interpreted as literal strings. (No variable substitution would take place, if that's what you're thinking.)
This bit here is probably the problem:
"+strHiringDate+",
"+strStartDate+",
"+strEndDate+",
"+strTerminatedDate+",
These would be parsed by Oracle as identifiers, not strings - because you've omitted the single quotes ('), and Oracle identifiers are optionally delimited by double quotes (").