SQL unique index without leading zeros - sql

I have set-up a table using the following SQL script:
CREATE TABLE MY_TABLE (
ID NUMBER NOT NULL,
CODE VARCHAR2(40) NOT NULL,
CONSTRAINT MY_TABLE PRIMARY KEY (ID)
);
CREATE UNIQUE INDEX XUNIQUE_MY_TABLE_CODE ON MY_TABLE (CODE);
The problem is that I need to ensure that CODE does not have a leading zero for its value.
How do I accomplish this in SQL so that a 40-char value without a leading zero is stored?

CODE VARCHAR2 NOT NULL CHECK (VALUE not like '0%')
sorry - slight misread on the original spec

If you can guarantee that all INSERTs and UPDATEs to this table are done through a stored procedure, you could put some code there to check that the data is valid and return an error if not.
P.S. A CHECK CONSTRAINT would be better, except that MySQL doesn't support them.

Related

How to name NOT NULL constraint in CREATE TABLE query

For a test tomorrow we're told to name our constraints
I know it's possible to create a constraint when you use ALTER TABLE
but can you add a name to a not null constraint when you CREATE TABLE?
f.e.
CREATE TABLE test (
test1 VARCHAR
CONSTRAINT nn_test1 NOT NULL (test1)
)
I get an error when trying to run this query. Am I writing it wrong?
The error I get is
ERROR: syntax error at or near "NOT"
LINE 3: CONSTRAINT nn_test1 NOT NULL (test1))
^
SQL state: 42601
Character: 56
You have two options to define a named not null constraint:
Inline with the column:
CREATE TABLE test
(
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL,
test2 integer --<< no comma because it's the last column
);
Or at the end of columns as an out-of-line constraint. But then you need a check constraint:
CREATE TABLE test
(
test1 VARCHAR,
test2 integer, --<< comma required after the last column
constraint nn_test1 check (test1 is not null)
);
This has become irrelevant, since you're not using SQL Server
First of all, you should always specify a length for a VARCHAR. Not doing so (in SQL Server variables, or parameters) may result in a string of just exactly ONE character in length - typically NOT what you want.
Then, you need to just specify the NOT NULL - there's no need to repeat the column name (actually this is the error) - if you're specifying the CONSTRAINT "inline" with the column definition (which is a perfectly legal and in my opinion the preferred way of doing this).
Try this code:
CREATE TABLE test
(
test1 VARCHAR(50)
CONSTRAINT nn_test1 NOT NULL
)
At least this is the CREATE TABLE statement that works in T-SQL / SQL Server - not sure about PostgreSQL (don't know it well enough, don't have it at hand to test right now).
I, a_horse_with_no_name, the two syntax:
constraint nn_test1 check (test1 is not null)
and
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL
are equivalent ? performance correctly ecc.
Because in first case the SQL server exception return the name nn_test so the system know exactly error.

Validating json string using CHECK constraint in Postgres (sql)

I have a table with below schema :
CREATE TABLE tbl_name (
id bigserial primary key,
phone_info json
);
Sample json data for phone_info column is given below .
{
"STATUS":{"1010101010":"1","2020202020":"1"},
"1010101010":"OK",
"2020202020":"OK"
}
Now I need to add a check constraint on phone_info column so that all key for "STATUS" ie(1010101010,2020202020) should exist as a (key,value) pair of phone_info column where value would be "OK".
So above sample data would satisfy the check constraint as there are following key value pair exists in phone_info column.
"1010101010":"OK"
"2020202020,":"OK"
I have tried below solution but this has not worked because array_agg function is not supported with check constraints.
ALTER TABLE tbl_name
ADD CONSTRAINT validate_info CHECK ('OK' = ALL(array_agg(phone_info->json_object_keys(phone_info->'STATUS'))) );
Can someone please help me out , Can I write a SQL function and use the function in check constraint?
With something like this I think you'll want an SQL function.
CREATE TABLE tjson AS SELECT '{
"STATUS":{"1010101010":"1","2020202020":"1"},
"1010101010":"OK",
"2020202020":"OK"
}'::json AS col;
perhaps something like:
CREATE OR REPLACE FUNCTION my_json_valid(json) RETURNS boolean AS $$
SELECT bool_and(coalesce($1->>k = 'OK','f'))
FROM json_object_keys($1->'STATUS') k;
$$ LANGUAGE sql IMMUTABLE;
... but remember that while PostgreSQL will let you modify that function, doing so can cause previously valid rows to become invalid in the table. Never modify this function without dropping the constraint then adding it back again.

Confused with Oracle Procedure with sequence, linking errors and filling null fields

I am trying to make a procedure that takes makes potential empty "received" fields use the current date. I made a sequence called Order_number_seq that populates the order number (Ono) column. I don't know how to link errors in the orders table to a entry in the Orders_errors table.
this is what i have so far:
CREATE PROCEDURE Add_Order
AS BEGIN
UPDATE Orders
CREATE Sequence Order_number_seq
Start with 1,
Increment by 1;
UPDATE Orders SET received = GETDATE WHERE received = null;
These are the tables I am working with:
Orders table
(
Ono Number Not Null,
Cno Number Not Null,
Eno Number Not Null,
Received Date Null,
Shipped_Date Date Null,
Creation_Date Date Not Null,
Created_By VARCHAR2(10) Not Null,
Last_Update_Date Date Not Null,
Last_Updated_By VARCHAR2(10) Not Null,
CONSTRAINT Ono_PK PRIMARY KEY (Ono),
CONSTRAINT Cno_FK FOREIGN KEY (Cno)
REFERENCES Customers_Proj2 (Cno)
);
and
Order_Errors table
(
Ono Number Not Null,
Transaction_Date Date Not Null,
Message VARCHAR(100) Not Null
);
Any help is appreciated, especially on linking the orders table errors to create a new entry in OrderErrors table.
Thanks in advance.
Contrary to Martin Drautzburg's answer, there is no foreign key for the order number on the Order_Errors table. There is an Ono column which appears to serve that purpose, but it is not a foreign as far as Oracle is concerned. To make it a foreign key, you need to add a constraint much like the Cno_FK on Orders. An example:
CREATE TABLE Order_Errors
(
Ono Number Not Null,
Transaction_Date Date Not Null,
Message VARCHAR(100) Not Null,
CONSTRAINT Order_Errors_Orders_FK FOREIGN KEY (Ono) REFERENCES Orders (Ono)
);
Or, if your Order_Errors table already exists and you don't want to drop it, you can use an ALTER TABLE statement:
ALTER TABLE Order_Errors
ADD CONSTRAINT Order_Errors_Orders_FK FOREIGN KEY (Ono) REFERENCES Orders (Ono)
;
As for the procedure, I'm inclined to say what you're trying to do does not lend itself well to a PROCEDURE. If your intention is that you want the row to use default values when inserted, a trigger is better suited for this purpose. (There is some performance hit to using a trigger, so that's a consideration.)
-- Create sequence to be used
CREATE SEQUENCE Order_Number_Sequence
START WITH 1
INCREMENT BY 1
/
-- Create trigger for insert
CREATE TRIGGER Orders_Insert_Trigger
BEFORE INSERT ON Orders
FOR EACH ROW
DECLARE
BEGIN
IF :NEW.Ono IS NULL
THEN
SELECT Order_Number_Sequence.NEXTVAL INTO :NEW.Ono FROM DUAL;
END IF;
IF :NEW.Received IS NULL
THEN
SELECT CURRENT_DATE INTO :NEW.O_Received FROM DUAL;
END IF;
END;
/
This trigger will then be executed on every single row inserted into the Orders table. It checks if the Ono column was NULL and replaces it with an ID from the sequence if so. (Be careful that you don't ever provide an ID that will later be generated by the sequence; it will get a primary key conflict error.) It then checks if the received date is NULL and sets it to the current date, using the CURRENT_DATE function (which I believe was one of the things you were trying to figure out), if so.
(Side note: Other databases may not require a trigger to do this and instead could use a default value. I believe PostgreSQL, for instance, allows the use of function calls in its DEFAULT clauses, and that is how its SERIAL auto-increment type is implemented.)
If you are merely trying to update existing data, I would think the UPDATE statements by themselves would suffice. Is there a reason this needs to be a PROCEDURE?
One other note. Order_Errors has no primary key. You probably want to have an auto-incrementating surrogate key column, or at least create an index on its Ono column if you only ever intend to select off that column.
There are a number of confusing things in your question:
(1) You are creating a sequence inside a procedure. Does this even compile?
(2) Your procedure does not have any parameters. It just updates the RECEIVED column of all rows.
(3) You are not telling us what you want in the MESSAGE column.
My impression is that you should first go "back to the books" before you ask questions here.
As for your original question
how to link errors in the orders table to a entry in the Orders_errors
table.
This is aleady (correctly) done. The Orders_error table contains an ONO foreign key which points to an order.

Replace into equivalent for postgresql and then autoincrementing an int

Okay no seriously, if a PostgreSQL guru can help out I'm just getting started.
Basically what I want is a simple table like such:
CREATE TABLE schema.searches
(
search_id serial NOT NULL,
search_query character varying(255),
search_count integer DEFAULT 1,
CONSTRAINT pkey_search_id PRIMARY KEY (search_id)
)
WITH (
OIDS=FALSE
);
I need something like REPLACE INTO for MySQL. I don't know if I have to write my own procedure or something?
Basically:
check if the query already exists
if so, just add 1 to the count
it not, add it to the db
I can do this in my php code but I'd rather all that be done in postgres C engine
You have to add a unique constraint first.
ALTER TABLE schema.searches ADD UNIQUE (search_query);
The insert/replace command looks like this.
INSERT INTO schema.searches(search_query) VALUES ('a search query')
ON CONFLICT (search_query)
DO UPDATE SET search_count = schema.searches.search_count + 1;

how to generate primary key values while inserting data into table through pl/sql stored procedure

I need to insert data into particular table through pl/sql stored procedure. My requirements are:
while inserting it should generate PRIMARY KEY values for a particular column;
it should return that PRIMARY KEY value to an output variable; and
for another column it should validate my string such that it should contain only characters, not integers.
You can generate primary key values as a surrogate key using an Oracle SEQUENCE. You can create a constraint on a column that uses TRANSLATE to check that no numeric digits exist in newly inserted/updated data.
Some example code, suitable for SQL*Plus:
CREATE SEQUENCE mysequence;
/
CREATE TABLE mytable (
pkidcol NUMBER PRIMARY KEY,
stringcol VARCHAR2(100)
);
/
ALTER TABLE mytable ADD (
CONSTRAINT stringnonnumeric
CHECK (stringcol = TRANSLATE(stringcol,'A0123456789','A'))
);
/
DECLARE
mystring mytable.stringcol%TYPE := 'Hello World';
myid mytable.pkidcol%TYPE;
BEGIN
INSERT INTO mytable (pkidcol, stringcol)
VALUES (mysequence.NEXTVAL, mystring)
RETURNING pkidcol INTO myid;
END;
/
In oracle I believe the "identity" column is best achieved with a sequence and an insert trigger that checks if the primary key columns is null and if so gets the next sequence and inserts it.
you can then use the "returning" clause to get the newly created primary key:
insert into <table> (<columns>) values (<values>) returning <prim_key> into <variable>;
the filtering of the string field I would personally handle in code before going to the database (if that is a possibility). Databases are notoriously inefficient at handling string operations.