Is it possible to define a column that auto increments which is a 12 digit number on a schema level?
So the sequence would go 000000000000, 000000000001, ...
You can create a sequence specifying min,max,start values. Then assign that sequence as a default. You commented that your need is "EAN-13, but the first digit is a constant", from this I assume you actually need a 13 digit number beginning with a fixed digit. You can use that fixed digit as the leading value of the sequence. Something like ( assumes that constant first digit is 5):
create sequence barcode_seq
increment 1
minvalue 5000000000000
maxvalue 5999999999999
start 5000000000000;
While sequences tend to be used as table keys that is not a requirement. Use the above sequence as the default value wherever the barcode is assigned. See fiddle.
Are you looking for the serial datatype? That's an auto-incrementing integer. It ranges from 1 to 2147483647, which is a bit less than 12 digits. If you need something bigger, you can switch to bigserial, that goes up to 9223372036854775807.
create table mytable (
id serial,
val text
);
insert into mytable (val) values ('foo'), ('bar');
select * from mytable;
id | val
-: | :--
1 | foo
2 | bar
Related
I have a column named invoice_number varchar(255) in the invoices table.
Here is some sample data:
20220010000000010
20220010000000011
20220010000000012
An invoice_number can have up to 17 digits. Here is the format in which it is generated:
Year(4 digits) + Number of invoice (3 digits) + profile number (10 digits)
At the moment, I have some data in this column as follows:
202200100000022.1
202200100000022.2
202200100000022.3
I would like to delete the decimal point which is the 2nd to the last digit and then add a zero on the 8th position (after 001 according to the sample data above) to handle all of these undesired invoice numbers.
Expected Output:
20220010000000221
20220010000000222
20220010000000223
What would be the best way to do this?
A safe way to do it is using REGEXP_REPLACE.
select invoice_number
, regexp_replace(invoice_number, '^([0-9]{4})([0-9]{3})([0-9]{8})[.]([0-9]+)$', '\1\20\3\4') as new_invoice_number
from (values
('202200100000022.1')
, ('202200100000022.2')
, ('202200100000022.3')
) q(invoice_number)
where invoice_number like '%.%';
invoice_number
new_invoice_number
202200100000022.1
20220010000000221
202200100000022.2
20220010000000222
202200100000022.3
20220010000000223
Test on db<>fiddle here
New to postgres and unsure how to accomplish the following. I have a table as follows:
create table if not exists my_table (
id int GENERATED BY DEFAULT AS IDENTITY primary key,
key int default 0
)
What I am trying to do is take an integer value (my_key) and if it's >= 0 and < 10 then add a leading zero (0) to it and insert it into my_table.key
I have tried to_char(my_key::integer,'09')::integer where my_key = 0 and it doesn't insert 00 within the key column.
Any help would be great.
Leading zeros don't change the value of an integer, so this is a question about formatting numbers.
If you want to display the id column with leading zeros, you could do that like this:
SELECT to_char(id, '00'), key
FROM "table";
The format 00 formats the number as a two-digit string with leasing zeros. If id is greater than 99, the number cannot be formatted like this, and you will get ##.
See the documentation for details about to_char and the available formats.
I hava data in my database and i need to select all data where 1 column number is between 1-100.
Im having problems, because i cant use - between 1 and 100; Because that column is character varying, not integer. But all data are numbers (i cant change it to integer).
Code;
dst_db1.eachRow("Select length_to_fault from diags where length_to_fault between 1 AND 100")
Error - operator does not exist: character varying >= integer
Since your column supposed to contain numeric values but is defined as text (or version of text) there will be times when it does not i.e. You need 2 validations: that the column actually contains numeric data and that it falls into your value restriction. So add the following predicates to your query.
and length_to_fault ~ '^\+?\d+(\.\d*)?$'
and length_to_fault::numeric <# ('[1.0,100.0]')::numrange;
The first builds a regexp that insures the column is a valid floating point value. The second insures the numeric value fall within the specified numeric range. See fiddle.
I understand you cannot change the database, but this looks like a good place for a check constraint esp. if n/a is the only non-numeric are allowed. You may want to talk with your DBA ans see about the following constraint.
alter table diags
add constraint length_to_fault_check
check ( lower(length_to_fault) = 'n/a'
or ( length_to_fault ~ '^\+?\d+(\.\d*)?$'
and length_to_fault::numeric <# ('[1.0,100.0]')::numrange
)
);
Then your query need only check that:
lower(lenth_to_fault) != 'n/a'
The below PostgreSQL query will work
SELECT length_to_fault FROM diags WHERE regexp_replace(length_to_fault, '[\s+]', '', 'g')::numeric BETWEEN 1 AND 100;
I have a column in a Postgresql table that is unique and character varying(10) type. The table contains old alpha-numeric values that I need to keep. Every time a new row is created from this point forward, I want it to be numeric only. I would like to get the max numeric-only value from this table for this column then create a new row with that max value incremented by 1.
Is there a way to query this table for the max numeric value only for this column?
For example, if this column currently has the values:
1111
A1111A
1234
1234A
3331
B3332
C-3333
33-D33
3**333*
Is there a query that will return 3333, AKA cut out all the non-numeric characters from the values and then perform a MAX() on them?
Not precisely what you asking, but something that I think will work better for you.
To go over all the columns, convert each to numbers, and then cast it to integer & return max.:
SELECT MAX(regexp_replace(my_column, '[^0-9]', '', 'g')::int) FROM public.foobar;
This gets you your max value... say 2999.
Now, going forward, consider making the default for your column a serial-like value, and convert it to text... that way you set the "MAX" once, and then let postgres do all the work for future values.
-- create simple integer sequence
CREATE SEQUENCE public.foobar_my_column_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 0;
-- use new sequence as default value for column __and__ convert to text
ALTER TABLE foobar
ALTER COLUMN my_column
SET DEFAULT nextval('publc.foobar_my_column_seq'::regclass)::text;
-- initialize "next value" of sequence to whatever is larger than
-- what you already have in your data ... say 3000:
ALTER SEQUENCE public.foobar_my_column_seq RESTART WITH 3000;
Because you're simply setting default, you don't change your current alpha-numeric values.
I figured it out. The following query works.
select text_value, regexp_replace(text_value, '[^0-9]+', '') as new_value from the_table;
Result:
text_value | new_value
-----------------------+-------------
4*215474 | 4215474
740024 | 740024
4*100535 | 4100535
42356 | 42356
CASH |
4*215474 | 4215474
740025 | 740025
740026 | 740026
4*5089655798 | 45089655798
4*15680 | 415680
4*224034 | 4224034
4*265718708 | 4265718708
I have a strange situation in the desing of my DB. I have the case that the type of value of a field can be a normal integer or a number between a range. I explain myself with a example:
the column age can be a number (18) or a range between (18-30). How I can represent this with postgresql?
Thx!
An integer range can represent both a single integer value and a range. The single value:
select int4range(18,18,'[]');
int4range
-----------
[18,19)
The ")" in the result above means exclusive.
The range:
select int4range(18,30,'[]');
int4range
-----------
[18,31)
There are a couple different ways to do this.
Store a VARCHAR
Store two values lower bound and upper bound
If there are only a select set of ranges you can create a lookup table for that set and store a foreign key to that lookup table.
You can make a bigger number, for example 18 x 1000 + 0 = 18000 for 18 and 18 x 1000 + 30 = 18030 for (18, 30).
When you retrieve it, you do first = round(number/1000) for the first number and second = number - first for the second number.
You can also store them as a point http://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6730.