I want to use a database like:
table wrongdoer (primarykey integer
ID, date)
table crime (numeric
foreign_key_to_wrongdoer, text crime)
I want my application (in python) to register a wrongdoer (which should give the entry a unique integer) and register the first crime against him. My idea is rather clumsy:
insert into wrongdoer(...)
id=cur.execute("select max(ID)")
//this is to select the most recent ID
cur.execute("insert into
crime('"+id+"'"crime+"'")")
That is, insert an entry, select its unique key from DB (assuming its the highest number), and then use it for the subsequent queries. Is there a better way to do it?
Check this function out:
http://www.sqlite.org/c3ref/last_insert_rowid.html
Related
I'm trying to insert a Number as an ID in a column in my database by a loop which sets the new ID by a Sequence. When I try to insert it, the row hasn't been created or the field where my number should be is null.
This only appears when I'm trying to insert the value of the current number of the sequence. Any other number can be inserted. The id isn't a primary key or foreign key, just a normal field. I have tried to insert it in a few different methods like to select it from a field or to hardcode the value in the insert script. If its hardcoded with, the value of the sid, no row is inserted.
insert into SCHULP_BEZIEHUNG (R_ID, B_ID,S_ID,WDH,HOTEL)
values(
SEQ_SCHULP_ID.NEXTVAL
,l_selected(i)
,(select distinct SSID from SCHULP_SCHULUNGEN where SID = :P2_ID and SSID is not null)
,5
,'test');
My expected result is that it inserts the nummber of SID in the column S_ID
Images of the Database:
What is this:
This only appears when I'm trying to insert the value of the current number of the sequence.
related to? If seq_schulp_id.nextval which - in your attempt - was actually seq_schulp_id.currval, then yes, it won't work until you fetch nextval first because currval isn't yet defined within the current session.
Another objection goes to :P2_ID which is an Apex page item. If you want to be able to use it, it isn't enough that you see it on the screen - it has to be put into session state. The simplest way to do that is to submit the page first, then run the process which will insert data.
On the other hand, you said that you hardcoded value (which value? :P2_ID?) but you still didn't manage to insert value into S_ID column. It means that the whole query:
select distinct SSID from SCHULP_SCHULUNGEN where SID = :P2_ID and SSID is not null
returned nothing.
You posted incomplete code (what is l_selected(i)?); I can't tell whether there's something else that might be wrong.
I'm working on a DB and would like to implement a system where a tables unique ID is generated by combining several other IDs/factors. Basically, I'd want an ID that looks like this:
1234 (A reference to a standard incrementing serial ID from another table)
10 (A reference to a standard incrementing serial ID from another table)
1234 (A number that increments from 1000-9999)
So the ID would look like:
1234101234
Additionally, each of those "entries" will have multiple time sensitive instances that are stored in another table. For these IDs I want to take the above ID and append a time stamp, so it'll look like:
12341012341234567890123
I've looked a little bit at PSQL sequences, but they seem like they're mostly used for simply incrementing up or down at certain levels, I'm not sure how to do this sort of concatenation in creating an ID string or whether it's even possible.
Don't do it! Just use a serial primary key id and then have three different columns:
otherTableID
otherTable2ID
timestamp
You can uniquely identify each row using your serial id. You can look up the other information. And -- even better -- you can create foreign key constraints to represent the relationships among the tables.
I'm not sure what do you want to achive, but
SELECT col_1::text || col_2::text || col_3::text || now()::text
should work. You should also add UNIQUE constraint on the column, i.e.
ALTER TABLE this_table ADD UNIQUE INDEX (this_new_column);
But the real question is: why do you want to do this? If you just want a unique meaningless ID, you need just to create column of type serial.
create procedure f_return_unq_id(
CONDITIONAL_PARAMS IN INTEGER,
v_seq in out integer
)
is
QUERY_1 VARCHAR2(200);
RESP INTEGER;
BEGIN
QUERY_1:='SELECT TAB1.SL_ID||TAB2.SL_ID||:v_seq||SYSTIMESTAMP FROM TABLE1 TAB1,TABLE2 TAB2 WHERE TAB1.CONDITION=:V_PARAMS';
BEGIN
EXECUTE IMMEDIATE QUERY_1 INTO RESP USING v_seq,CONDITIONAL_PARAMS;
EXCEPTION
when others then
DBMS_OUTPUT.PUT_LINE(SQLCODE);
END;
v_seq:=RESP;
EXCEPTION
when others then
DBMS_OUTPUT.PUT_LINE(SQLCODE);
END;
pass the v_seq to this procedure as your sequence number 1000-9999 and conditional parameters if any are there.
The primary key of my table is an Identity column of an ID. I want to be able to insert a new row and have it know what the last ID in the table currently is and add one to it. I know I can use Scope Identity to get the last inserted column from my code, but I am worried about people manually adding entries in the database, because they do this quite often. Is there a way I can look at the last ID in the table and not just the last ID my code inserted?
With a SQL Identity column, you don't need to do anything special. This is the default behavior. SQL Server will handle making sure you don't have collisions regardless of where the inserts come from.
The ##Identity will pull the latest identity, and scope_identity will grab the identity from the current scope.
A scope is a module: a stored procedure, trigger, function, or batch. Therefore, if two statements are in the same stored procedure, function, or batch, they are in the same scope.
If you don't want to allow manual entries to the primary column, then you can add Identity constraint to it along with primary key constraint.
Example, while creating a table,
CREATE Table t_Temp(RowID Int Primary Key Identity(1,1), Name Varchar(50))
INSERT Into t_Temp values ('UserName')
INSERT Into t_Temp values ('UserName1')
SELECT * from t_Temp
You can query the table and get the next available code in one SQL query:
SELECT COALESCE(MAX(CAST("RowID" AS INT)),0) +1 as 'NextRowID' from <tableName>
The "0" here is a default, meaning if there are no rows found, the first code returned would be (0+1) =1
Generally I have 999 instead of the 0 as I like my RowID/primary key etc. to start at 1000.
I'm trying to make a blog system of sort and I ran into a slight problem.
Simply put, there's 3 columns in my article table:
id SERIAL,
category VARCHAR FK,
category_id INT
id column is obviously the PK and it is used as a global identifier for all articles.
category column is well .. category.
category_id is used as a UNIQUE ID within a category so currently there is a UNIQUE(category, category_id) constraint in place.
However, I also want for category_id to auto-increment.
I want it so that every time I execute a query like
INSERT INTO article(category) VALUES ('stackoverflow');
I want the category_id column to be automatically be filled according to the latest category_id of the 'stackoverflow' category.
Achieving this in my logic code is quite easy. I just select latest num and insert +1 of that but that involves two separate queries.
I am looking for a SQL solution that can do all this in one query.
This has been asked many times and the general idea is bound to fail in a multi-user environment - and a blog system sounds like exactly such a case.
So the best answer is: Don't. Consider a different approach.
Drop the column category_id completely from your table - it does not store any information the other two columns (id, category) wouldn't store already.
Your id is a serial column and already auto-increments in a reliable fashion.
Auto increment SQL function
If you need some kind of category_id without gaps per category, generate it on the fly with row_number():
Serial numbers per group of rows for compound key
Concept
There are at least several ways to approach this. First one that comes to my mind:
Assign a value for category_id column inside a trigger executed for each row, by overwriting the input value from INSERT statement.
Action
Here's the SQL Fiddle to see the code in action
For a simple test, I'm creating article table holding categories and their id's that should be unique for each category. I have omitted constraint creation - that's not relevant to present the point.
create table article ( id serial, category varchar, category_id int )
Inserting some values for two distinct categories using generate_series() function to have an auto-increment already in place.
insert into article(category, category_id)
select 'stackoverflow', i from generate_series(1,1) i
union all
select 'stackexchange', i from generate_series(1,3) i
Creating a trigger function, that would select MAX(category_id) and increment its value by 1 for a category we're inserting a row with and then overwrite the value right before moving on with the actual INSERT to table (BEFORE INSERT trigger takes care of that).
CREATE OR REPLACE FUNCTION category_increment()
RETURNS trigger
LANGUAGE plpgsql
AS
$$
DECLARE
v_category_inc int := 0;
BEGIN
SELECT MAX(category_id) + 1 INTO v_category_inc FROM article WHERE category = NEW.category;
IF v_category_inc is null THEN
NEW.category_id := 1;
ELSE
NEW.category_id := v_category_inc;
END IF;
RETURN NEW;
END;
$$
Using the function as a trigger.
CREATE TRIGGER trg_category_increment
BEFORE INSERT ON article
FOR EACH ROW EXECUTE PROCEDURE category_increment()
Inserting some more values (post trigger appliance) for already existing categories and non-existing ones.
INSERT INTO article(category) VALUES
('stackoverflow'),
('stackexchange'),
('nonexisting');
Query used to select data:
select category, category_id From article order by 1,2
Result for initial inserts:
category category_id
stackexchange 1
stackexchange 2
stackexchange 3
stackoverflow 1
Result after final inserts:
category category_id
nonexisting 1
stackexchange 1
stackexchange 2
stackexchange 3
stackexchange 4
stackoverflow 1
stackoverflow 2
Postgresql uses sequences to achieve this; it's a different approach from what you are used to in MySQL. Take a look at http://www.postgresql.org/docs/current/static/sql-createsequence.html for complete reference.
Basically you create a sequence (a database object) by:
CREATE SEQUENCE serials;
And then when you want to add to your table you will have:
INSERT INTO mytable (name, id) VALUES ('The Name', NEXTVAL('serials')
I want to store different versions of different texts and other data in a table. For the texts, my table looks like this:
id BigSerial, PRIMARY KEY
version Integer
text Text
origin BigInt
Now I want to store different versions of texts in this table like this:
1,0,"My Text, first Version",null
2,1,"My Text, second Version",1
3,0,"My 2nd Text v1",null
4,1,"My 2nd Text v2",3
I don't know yet how to query for the row with the highest version number for each set of texts.
The Bigserial id number serves no useful purpose.
create temp table my_table (
id integer not null,
version integer not null check(version > 0),
-- Give a lot of thought to whether text should also be unique. *I* think
-- it probably should, but it's really application-dependent.
text Text not null unique,
primary key (id, version)
);
insert into my_table values
(1, 1, 'My Text, first Version'),
(1, 2, 'My Text, second Version'),
(2, 1, 'My 2nd text v1'),
(2, 2, 'My 2nd text v2')
Number of versions for every id.
select id, count(*)
from my_table
group by id;
Current version for every id.
with current_ver as (
select id, max(version) as version
from my_table
group by id
)
select m.* from my_table m
inner join current_ver c on c.id = m.id and c.version = m.version
Although I wrote that with a common table expression, you probably want to create a view of current versions. I'd think most applications that access this data will need the current version.
Since not all of the set of texts may get new versions at the same rate, there's no real way of making an assertion on version number that won't have to involve both the id and the origin.
For instance, to know that "5" is the latest version of a particular text set, you'll have to establish that there is no version "6". The way to do that is to see if there is a row with a version "6" that has an origin to the row with version "5". But this just reduces to finding a row that has no other row claiming it as an origin point; you don't need the version number.
So, you can rephrase the question of "do I have the highest version number" as "is there no other row that has my id as its origin". If there is no other row, then this is your newest row, and you can return your result. You can accomplish this with something like the following query:
select t.id
from table parent
left join table descendants on parent.id = descendants.origin
where descendants.id is null;
The only rows in the resulting joined table where descendant.id will be null are the ones that are the newest. Notice that both parent and descendants are aliased from the same table. This is what is known as a "self-join", and is handy to do when you have hierarchical data (like your versioning mechanism) stored within a single table.
It is worth noting, though, that this only finds the newest version for you. If you want to know which version this is, then you will definitely benefit from having your version column. Otherwise, you will end up having to do a recursive query, since you won't know the depth of your version list up front. No one likes writing those.
Hope this helps.
Temporal tables extension might help, if you don't want to roll your own that is...
https://github.com/arkhipov/temporal_tables