Return Next Available PK in a Collection of Tables - tsql

I'm building a report from a series of known tables and their primary keys, e.g.:
BOOKS.bookid
AUTHORS.authorid
GENRE.genreid
What I would like to do is build a t-sql report that simply shows the table, the primary key, and the next available PK, e.g.:
**tabl_name prim_key avail_key**
BOOKS BOOKID 281
AUTHORS AUTHORID 29
GENRE GENREID 18
I already have the table name and its PK by using the information_schema, but somehow joining that with the actual table to derive its next available PK is proving elusive. I'm guessing there's some sort of dynamic sql with cursors solution, but that's maxing my sql skills out.

Try this:
SELECT Col.TABLE_NAME, Col.Column_Name, ident_current(Col.TABLE_NAME) from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
WHERE
Col.Constraint_Name = Tab.Constraint_Name
AND Col.Table_Name = Tab.Table_Name
AND Constraint_Type = 'PRIMARY KEY '
By the way, most of the above came from this answer:
https://stackoverflow.com/a/96049/37613

Related

How to insert new rows only on tables without Primary or Foreign Keys?

Scenario: I have two tables. Table A and Table B, both have the same exact columns. My task is to create a master table. I need to ensure no duplicates are in the master table unless it is a new record.
problem: Whoever built the tables did not assign a Primary Key to the table.
Attempts: I attempted running an INSERT INTO WHERE NOT EXISTS query (below as an example not the actual query I ran)
Question: the portion of the query below WHERE t2.id = t1.id confuses me, my table has a multitude of columns, there is no id column like I said it has no PRIMARY key to anchor the match, so, in a scenario where all I have are values without primary keys, how can I append only new records? Also, perhaps I am going about this the wrong way but are there any other functions or options through TSQL worth considering? Maybe not an INSERT INTO statement or perhaps something else? My SQL skills aren't yet that advance so I am not asking for a solution but perhaps ideas or other methods worth considering? Any ideas are welcome.
INSERT INTO TABLE_2
(id, name)
SELECT t1.id,
t1.name
FROM TABLE_1 t1
WHERE NOT EXISTS(SELECT id
FROM TABLE_2 t2
WHERE t2.id = t1.id)
If I understand your question correctly, you would need to amend the SQL sample you posted by changing the condition t2.id = t1.id to whatever columns you do have.
Say your 2 tables have name and brand columns and you don't want duplicates, just change the sample to:
WHERE t2.name = t1.name
AND t2.brand = t1.brand
This will ensure you don't insert and rows in table 2 from table 1 which are duplicates. You would have to make sure the where condition contains all columns (you said the table schemas are identical).
Also, the above code sample copies everything into table 2 - but you said you want a master table - so you'd have to change it to insert into the master table, not table 2.

How to query "has no linked records in this table"

I have two simple tables: one with primary key id, and two with primary key id and a foreign key oneId.
I want to get all rows from one with no references in two.oneId.
I could do
SELECT ... FROM one LEFT JOIN two ON two.oneId = one.id WHERE two.id IS NULL
SELECT ... FROM one WHERE NOT exists(SELECT 1 FROM two WHERE oneId = one.id)
SELECT ... FROM one WHERE id NOT IN (SELECT oneId FROM two)
probably other options exist
Which option is better, and why?
The second choice is the best – it will be translated to an antijoin.
Number one looks pretty good too, it might have the same execution plan.

Update or insert with outer join in postgres

Is it possible to add a new column to an existing table from another table using insert or update in conjunction with full outer join .
In my main table i am missing some records in one column in the other table i have all those records i want to take the full record set into the maintable table. Something like this;
UPDATE maintable
SET all_records= othertable.records
FROM
FULL JOIN othertable on maintable.col = othertable.records;
Where maintable.col has same id a othertable.records.
I know i could simply join the tables but i have a lot of comments in the maintable i don't want to have to copy paste back in if possible. As i understand using where is equivalent of a left join so won't show me what i'm missing
EDIT:
What i want is effectively a new maintable.col with all the records i can then pare down based on presence of records in other cols from other tables
Try this:
UPDATE maintable
SET all_records = o.records
FROM othertable o
WHERE maintable.col = o.records;
This is the general syntax to use in postgres when updating via a join.
HTH
EDIT
BTW you will need to change this - I used your example, but you are updating the maintable with the column used for the join! Your set needs to be something like SET missingcol = o.extracol
AMENDED GENERALISED ANSWER (following off-line chat)
To take a simplified example, suppose that you have two tables maintable and subtable, each with the same columns, but where the subtable has extra records. For both tables id is the primary key. To fill maintable with the missing records, for pre 9.5 versions of Postgres you must use the following syntax:
INSERT INTO maintable (SELECT * FROM subtable s WHERE NOT EXISTS
(SELECT 1 FROM maintable m WHERE m.id = s.id));
Since 9.5 there is a (preferred) alternative:
INSERT INTO maintable (SELECT * FROM subtable) ON CONFLICT DO NOTHING;
This is preferred because (apart from being simpler) it avoids the situation that has been known to arise in the former, where a race condition is created between the INSERT and the sub-SELECT.
Obviously when the columns are different, you need to specify in the INSERT statement which columns are inserted from which. Something like:
INSERT INTO maintable (id, ColA, ColB)
(SELECT id, ColE, ColG FROM subtable ....)
Similarly the common field might not be id in both tables. However, the simplified example should be enough to point you in the right direction.

What strategy to use: store additional informational field in main table or in separate with on-to-one/many relation?

I have main entity and sometimes customer want new fields in this entity.
As them used as informational and never be as criteria in queries I think that storing them in main table may be worse practice (especially updating schema each update).
What if organise additional table:
create table ENTITY_FIELD (
ENTITY_ID,
FIELD_NAME,
FIELD_TYPE,
FIELD_VALUE,
primary key (ENTITY_ID, FIELD_NAME));
and join one-to-one with ENTITY table on f.ENTITY_ID = e.ID and f.FIELD_NAME = 'field1' when I need field1 field? Like:
select e.*, f1.FIELD_VALUE, f2.FIELD_VALUE from ENTITY e
left join ENTITY_FIELD f1 on f1.ENTITY_ID = e.ID and f1.FIELD_NAME = 'field1'
left join ENTITY_FIELD f2 on f2.ENTITY_ID = e.ID and f2.FIELD_NAME = 'field2'
Or add fields to ENTITY and live with 100-200 fields in?
How about hold all fields in separate table:
create table ENTITY_FIELD (
ENTITY_ID,
FIELD1,
FIELD2,
FIELD3,
FIELD4,
...
primary key (ENTITY_ID));
so you only join on f.ENTITY_ID = e.IE? Like:
Like:
select e.*, f.FIELD1, f.FIELD2 from ENTITY e, ENTITY_FIELD f
where e.ID = f.ENTITY_ID
I use Oracle/Java/Hibernate but seems that question about general design.
There is really no right or wrong answer and I guess you should employ a method that reduces the need to recompile and or remap your entities.
I have a personal rule for this. If an option dictates business rule logic or program flow it should be a type field in a main entity table and would require a recompilation. If you are storing arbitrary values such as ui preferences and size info, custom images, user parameter values, or custom labels, basically things that do not require values and ideally have default values, and more importantly, the system will function with or without the values being set then you can put these in some kind of setting table. I use two straightforward UserSettings and UserSettingsConfiguration tables similar to your approach above.
UserSetting
----------
UserSettingID(PK),
SettingName,
Description
Category
UserSettingConfiguration
------------------------
UserSettingConfigurationID(PK),
UserSettingID (FK UserSetting.UserSettingID),
UserID (FK)
Value

When is a Deadlock not a Deadlock?

I'm asking this question because I'm getting a deadlock from time to time that I don't understand.
This is the scenario:
Stored Procedure that updates table A:
UPDATE A
SET A.Column = #SomeValue
WHERE A.ID = #ID
Stored Procedure that inserts into a temp table #temp:
INSERT INTO #temp (Column1,Column2)
SELECT B.Column1, A.Column2
FROM B
INNER JOIN A
ON A.ID = B.ID
WHERE B.Code IN ('Something','SomethingElse')
I see that there could possibly be a lock wait but I fail to see how a deadlock would occur, am I missing something obvious?
EDIT:
The SPs that I typed here are obviously simplified versions but I'm using the columns involved. The structure of both tables would be:
CREATE TABLE A (ID IDENTITY
CONSTRAINT PRIMARY KEY,
Column VARCHAR (100))
CREATE TABLE B (ID IDENTITY
CONSTRAINT PRIMARY KEY,
Code VARCHAR (100))
Try this since its causeing locks specify for the tables name the table hint and keyword:
WITH(NOLOCK)
So some thing like this for your scenario:
INSERT INTO #temp (Column1,Column2)
SELECT B.Column1, A.Column2
FROM B WITH(NOLCOK)
INNER JOIN A WITH(NOLOCK)
ON A.ID = B.ID
WHERE B.Code IN ('Something','SomethingElse')
See how you go then.
You can lookup table hint also for tsql, sql server to see which one suits you best. The one I specified NOLCOK will not cause locks and also it will skip locked rows as some other process is using them, so if you dont care you can use it.
I am not sure with temp tables but you can also use table hints with INSERT, INSERT INTO WITH(TABLE_HINT).