Slo-Tech

» »

[SQL] primary key inkrementalno dodajanje

[SQL] primary key inkrementalno dodajanje

«
1
2

korenje3 ::

Pri nas je SQL slabo skonfiguriran in ne dodaja samodejno primary key vrednosti.

npr.:
INSERT INTO [Product] ([ProductName], [SupplierId], [Package])
	OUTPUT inserted.[Id]
	VALUES
	(CAST('TEST 2 LALA' AS NVARCHAR(50)), PARSE('1' AS INT USING 'Sl-SI'), CAST('24 - 12 oz bottles' AS NVARCHAR(30)));


Če imam še primary key kolono 'Id' (int). Kakšen mora biti ukaz potem, da mi avtomatsko doda Id vrednost inkrementalno?
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

Besna Glista ::

Ne rabiš nič v insertu, ker ti bo sam vstavil vrednost auto increment polja.

AndrejS ::

@Besna Glista - preberi si še 1x njegov post.

@korenje3 Kateri SQL uporabljaš ?

zavajon ::

Če gre za T-SQL, moraš kreirati tabelo z identity.

CREATE TABLE Product  
(  
 id int IDENTITY, 
... 


V MySQL je tako:
CREATE TABLE Product (
    id int NOT NULL AUTO_INCREMENT,
...

korenje3 ::

Kaj pa če ne smem pipat tabele?

Pri insertu mi napiše da Id ne sme biti null. Samodejno mi pa ne doda številke.

Strežnik je pa tsql.
Gre se pa za largo bazo podjetja perftech. Mogoče če kdo dela v tem podjetju da bi vedel ustrezen ukaz...? Ali se zaporedje šifr hrani kje drugje?
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

Zgodovina sprememb…

  • spremenil: korenje3 ()

DamijanD ::

Če hočeš, da se bo ID sam polnil, je potrebno polje definirat, da je identity. (Vsaj pri mssql imaš problem, ker tega ne moreš nastaviti na obstoječem polju...)

Vazelin ::

Lol korenje brez nič ne bo nič:))
Lahko uporabiš sekvenco samo potem moraš vedno filat s sekvenco
I got 99 problems but 2.5usd tezus ain't one.

Macario ::

DamijanD je izjavil:

Če hočeš, da se bo ID sam polnil, je potrebno polje definirat, da je identity. (Vsaj pri mssql imaš problem, ker tega ne moreš nastaviti na obstoječem polju...)


lahko na obstoječem polju nastaviš identity. Ravno sedaj poskusil.

Sem šel gledat skripto v sql managerju ob spremembi tabele in tehnično je to res, da ne moreš obstoječu stolpcu spremeniti identity.
Namreč skripta naredi temp tabelo z identity on, skopira podatke noter, dropne staro tabelo in preimenuje novo temp tabelo.

Iz uporabniškega vidika je res, da lahko doda identity na obstoječi column toda zadaj pa je v resnici nova tabela, nov column.

Zgodovina sprememb…

  • spremenilo: Macario ()

zavajon ::

korenje3 je izjavil:

Kaj pa če ne smem pipat tabele?

Pri insertu mi napiše da Id ne sme biti null. Samodejno mi pa ne doda številke.

Strežnik je pa tsql.
Gre se pa za largo bazo podjetja perftech. Mogoče če kdo dela v tem podjetju da bi vedel ustrezen ukaz...? Ali se zaporedje šifr hrani kje drugje?

Potem naredi trigger, ki pri insertu izračuna max(id) in doda naslednjo vrednost.
Če pa triggerja ne moreš narediti, boš moral najprej prebrati max(id) in nato insertati ta max(id)+1.

Ahim ::

zavajon je izjavil:

Potem naredi trigger, ki pri insertu izračuna max(id) in doda naslednjo vrednost.
Če pa triggerja ne moreš narediti, boš moral najprej prebrati max(id) in nato insertati ta max(id)+1.

To je nocna mora za vsako resno bazo, do katere ne dostopa samo en klient naenkrat, ki izvaja samo eno transakcijo naenkrat in na kateri ni nobenih rollbackov transakcij.

Zgoraj so lepo napisali, da naj nastavi identity. Largo pa Perftech pa ... ce nimas dostopa do tabele, naj pa oni naredijo.

korenje3 ::

Imam dostop, samo njihov program uporablja SQL bazo, tako da ne smem spreminjat. V bistvu bi moral izvršit enak ukaz kot ga njihov program. To da se ugotavlja kateri je zadnji zapis pa verjetno ne pride v poštev, ker v primeru da 2 naenkrat izvršita ukaz lahko duplicira.
Mi pa ni jasno zakaj je inkrementiranje izklopljeno sploh. Zaradi hitrosti?
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

Zgodovina sprememb…

  • spremenil: korenje3 ()

kuall ::

daš v transakcijo, če te skrbi, da se bo med stavka:

get id
insert with id

vrinil get id od drugega uporabnika

transakcija bo zaklenila tabelo, da v času ne bo noben mogel vstavljat


ampak nisem zihetr, da je treba tako komplicirat, v praksi takega kompliciranja nisem videl, ni mi pa jasno zakaj ne, ker teoretično je res možno, da se vmes vrine stavbek od drugega uporabnika

subquery je najbolj zanesljiva rešitev. jaz se transakcijam izogibam, ker če jo pustiš odprto zna bit mau pizdarija.

create table _testz (id int)

insert into _testz (id) values (isnull ((select max (id) from _testz), 0) + 1)
insert into _testz (id) values (isnull ((select max (id) from _testz), 0) + 1)
insert into _testz (id) values (isnull ((select max (id) from _testz), 0) + 1)

select* from _testz

kuall ::

lahko z sql profilerjem pogledš, kakšen ukaz uporablja njihov program in samo tisto prekopiraš v svojo kodo

kuall ::

aja vrstni red bi moral biti takle, da bi se zbrkljalo:

uporabnik2: get id
uporabnik1: get id
uoprabnik1: insert with id
uporabnik2: insert with id

torej totalen nelogičen vrstni red.
zato ti ni treba skrbet. razen če bi se vsak query izvrševal v neki svoji niti, in bi vsaka nit dobila neko svojo random prioriteto in vrstni red izvrševanja bi lahko prišlo do zgornjega zbrkljanja, ampak po moje se sql ukazi izvajajo lepo zaporedno, zato ni treba komplicirat s transkacijami itd.

smacker ::

Kuall pusti sql, ni to za tebe zgleda.

Zgodovina sprememb…

  • predlagalo izbris: kuall ()

kuall ::

kaj sem narobe napisal?

Lonsarg ::

To so najhujše vrste bugi/napake, če tega nimaš porihtanega v transakciji, to imamo bič za take ki ne bi to pazili!

kuall ::

da daš get id insert id v transakcijo?
sem pregledal veliko sql kode in nikoli videl tega v transakciji.
ni tako hud bug, bi ti itak javil napako, da je id že zaseden (če imaš unique index, kar ga ponavadi imaš)

jype ::

kuall je izjavil:

kaj sem narobe napisal?
Skoraj vse.

Zgodovina sprememb…

  • predlagalo izbris: kuall ()

kuall ::

moderatorji? se boste zmigal ali boste pustili, da bo ta forum gnoj?

smacker ::

kuall je izjavil:

kaj sem narobe napisal?

Vse, razen tega da je treba uporabit transakcijo, če nočeš da te kaj prekine. Ampak za ta problem tudi to ni najbolj ustrezna rešitev, namreč MAX(id)+1 lahko privede do nevšečnosti, ko nov record dobi isti ID, kot ga je pred tem imel nek drug record, ki je sedaj izbrisan.

kuall ::

kaj je s tem narobe:
insert into _testz (id) values (isnull ((select max (id) from _testz), 0) + 1)

jype ::

kuall je izjavil:

kaj je s tem narobe:
Race condition @ Wikipedia

kuall ::

smacker je izjavil:

je treba uporabit transakcijo, če nočeš da te kaj prekine.

transakcija ti v tem primeru nič ne pomaga, ker select max ne zaklene tabele, zaklene jo šele, če pišeš v njo

vse si narobe napisal, nimaš pojma

ok spet sem moral sam najti rešitev, fakin jypeti neuporabni:

create table _test55 (id int)
begin transaction
declare @id int = isnull (((select max(id) from _test55 with (TABLOCKX ))), 0) + 1
insert into _test55 (id) values (@id)
commit

Zgodovina sprememb…

  • spremenilo: kuall ()

jype ::

Še vedno pa ne razumeš, kaj si storil?

Šokantno.

No, naj ti pomagam:

Linearizability @ Wikipedia

Read%E2%80%93modify%E2%80%93write @ Wikipedia

Zgodovina sprememb…

  • predlagalo izbris: kuall ()

kuall ::

ne mi limat te debilne wikipedia članke. vem da je teoretično možno, da se sql ukazi izvajajo v random vrstnem redu, saj to sem že napisal.
zanima me kako se sql obnaša v praksi. po moje ni tako random, zakaj bi bil.

Vazelin ::

Jype: zakaj korenju ne napišes rešitve lol. Boli njega k za lineariablitiy :D on rabi rešitev
I got 99 problems but 2.5usd tezus ain't one.

kuall ::

zato ker ge ne ve, ampak blefira kot ponavadi. saj smo mu v eni temi že dokazali, da je blefer, se ne spomniš. ko je trdil, da ima naloga rešitev in da smo loleki, ker rešitve ne vemo, na koncu pa smo dokazali, da rešitve ni za nalogo.

bleferji daleč pridejo, zato ni za podcenjevat tega njegovega skilla.

jype ::

Vazelin je izjavil:

zakaj korenju ne napišes rešitve lol
Ker nima zadostnega dostopa, da bi jo izvedel.

kuall je izjavil:

zato ker ge ne ve, ampak blefira kot ponavadi. saj smo mu v eni temi že dokazali, da je blefer, se ne spomniš. ko je trdil, da ima naloga rešitev in da smo loleki, ker rešitve ne vemo, na koncu pa smo dokazali, da rešitve ni za nalogo.
Dokazali ste, da nimate pojma o matematiki.

kuall je izjavil:

zanima me kako se sql obnaša v praksi. po moje ni tako random, zakaj bi bil.
V praksi boš na težave naletel prej, kot si domišljaš.

Zgodovina sprememb…

  • spremenilo: jype ()

Vazelin ::

Btw korenje: nisi ti v Forex penziji? :)
I got 99 problems but 2.5usd tezus ain't one.

jype ::

Vazelin je izjavil:

Btw korenje: nisi ti v Forex penziji? :)
Očitno ne.

Spura ::

kuall je izjavil:

ne mi limat te debilne wikipedia članke. vem da je teoretično možno, da se sql ukazi izvajajo v random vrstnem redu, saj to sem že napisal.
zanima me kako se sql obnaša v praksi. po moje ni tako random, zakaj bi bil.

Ne vem od kod ti taka vera, da SQL server ukaze on enega connectiona vse izvede do konca, preden gre na druge ukaze. Mislim,
tvoja trditev
ampak po moje se sql ukazi izvajajo lepo zaporedno, zato ni treba komplicirat s transkacijami
je povsem zmotna. "Po tvoje" je povsem neinformirano mnenje. Baze izvajajo ukaze iz vecih niti, to so OS niti, ne green threadi, torej tudi ce bi DB hotel razvrscati izvajanje procesov, tega ne more, ker scheduler za niti je v OS kernelu in ta pojma nima kaj baza dela, in lahko ustavi izvajanje niti na vsakem strojnem ukazu.

Manjka ti osnovno znanje o tem podrocju.

korenje3 ::

kuall je izjavil:

smacker je izjavil:

je treba uporabit transakcijo, če nočeš da te kaj prekine.

transakcija ti v tem primeru nič ne pomaga, ker select max ne zaklene tabele, zaklene jo šele, če pišeš v njo

vse si narobe napisal, nimaš pojma

ok spet sem moral sam najti rešitev, fakin jypeti neuporabni:

create table _test55 (id int)
begin transaction
declare @id int = isnull (((select max(id) from _test55 with (TABLOCKX ))), 0) + 1
insert into _test55 (id) values (@id)
commit


Torej ni možno da se med declare @id in insert nekomu drugemu oba ukaza izvršita prej?
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

kuall ::

ampak to pride do izraza v ekstremnih pogojih, v kakšnih naprimer?
v takih ne, če imaš bazo, 2 računalnika povezana na njo in vsak povezan na njo preko (počasnega) interneta. v tem primeru se sigruno 2 sql zaporedna queryja izvedeta do konca, preden se izvaja drug.
mogoče če imaš multiprocesor računalnik in milijone uoprabnikov..

zdele gledam sql kodo od enega večjega programa. kar lepo uporablja select max id in potem dela insert tega idja brez transkacija. očitno tudi njim manjkajo osnove.

ja ta rešitev drži, lahko jo uporabiš brez skrbi:

create table _test55 (id int)
begin transaction
declare @id int = isnull (((select max(id) from _test55 with (TABLOCKX ))), 0) + 1
insert into _test55 (id) values (@id)
commit

Zgodovina sprememb…

  • spremenilo: kuall ()

jype ::

korenje3 je izjavil:

Torej ni možno da se med declare @id in insert nekomu drugemu oba ukaza izvršita prej?
Seveda je možno. Ne le možno, celo neizogibno v kakršnihkoli sistemih, kjer baza dejansko dela.

kuall je izjavil:

zdele gledam sql kodo od enega večjega programa. kar lepo uporablja select max id in potem dela insert tega idja brez transkacija. očitno tudi njim manjkajo osnove.
Očitno.

Verjetnost, da s takim početjem ustvarijo nekonsistenten zapis, s številom transakcij narašča skoraj eksponentno na vsakem sodobnem RDBMS, zato pa vsak sodoben RDBMS implementira reči, ki to preprečijo, samo uporabiti ga moraš.

Zgodovina sprememb…

  • spremenilo: jype ()

korenje3 ::

V poslovnem okolju "verjetnost napake" odpade. Zadeva mora funkcionirat 100% ali pa izpisat da je bila napaka (key value že obstaja).
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

kuall ::

identity kolona je ta najbolj varen mehanizem?

kaj pa če hočeš imeti autoinc subkolono, npr id, subid? uporabit transakcijo + unique composite index (id, subid) bo kle sigurna rešitev.

jype ::

korenje3 je izjavil:

V poslovnem okolju "verjetnost napake" odpade. Zadeva mora funkcionirat 100% ali pa izpisat da je bila napaka (key value že obstaja).
Potem pa poiščite nekoga, ki se spozna na te reči, da bo razvil rešitev, ki ne uporablja IEEE754 matematike za delo s finančnimi podatki.

korenje3 ::

Jutri pogledam kakšna je ta kolona "Šifra" v resnici s sql explorerjem in zakaj nima auto increment.
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

kuall ::

prilimiaj kodo ki jo dobiš z sql profilerjem, kako njihov program dela insert. me zanima, če uporablja transakcijo.

korenje3 je izjavil:

V poslovnem okolju "verjetnost napake" odpade. Zadeva mora funkcionirat 100% ali pa izpisat da je bila napaka (key value že obstaja).


Ti pa ziher nisi programer.
sej lahko po insertu komot narediš preverbo, ali so vsi idji unique ali se je v tem času vrinil en drug isti id, če te tako skrbi, in javiš napako. ampak to je brezveze bluzeneje.

Zgodovina sprememb…

  • spremenilo: kuall ()

kuall ::

kuall je izjavil:

kaj je s tem narobe:
insert into _testz (id) values (isnull ((select max (id) from _testz), 0) + 1)


no še na tole moram sam odgovorit:

compiler to prevede v dve izjavi, najprej izračuna subquery, nato glavni query. ni dost drgač kot da bi napisal query1 in query2.
med te izjavi se teoretično lahko vrine drug uporabnik s svojim idjem, ki je enak.

ampak ta debata je mim zato, ker so v praksi vsi idji unique index. če že pride do takega primera (zelo redko) bo uporabnik dobil dobil napako, da id že obstaja in bo pač ponovil insert.

me pa zanima od vas "veleumov", če znate napisat test program, ki bo znal ponoviti to napako, da se bo id od drugega uoprabnika vrinil med select max id in insert id. seveda ne znate, ker ste blefereji.

jype ::

kuall je izjavil:

seveda ne znate, ker ste blefereji.
Ne sodi drugih po sebi.

Multi-master replication @ Wikipedia

korenje3 ::

Za sql profiler nimam dostopa. Kolona pa nima avtomatskega dodajanja vklopljenega. Tako da ne morem vedet kako program dajaja nove vrstice v tabelo...
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

no comment ::

korenje3 je izjavil:

Tako da ne morem vedet kako program dajaja nove vrstice v tabelo...

Glede na to, da polje ni identity lahko "veš", da dodaja po "kmečko". Glede na to, da praviš, da je to polje PK, potem verjetno enostavno ugotovi zadnji ID, ga inkrementira in poskusi z insertom. Če insert crkne, poskusi z naslednjim itd.

korenje3 ::

Tako je kot si rekel, verjetno dodaja po kmečko. Se vidi da so na perftech pocarji... kasirajo pa po 100€/h za sestanek. Že po imenih kolon v različnih tabelah se vidi, da je vsak "programer" delal nekaj po svoje s svojim omejenim znanjem.
Pentium I7 3770k@4,5Ghz; 16GB RAM@2133MHz; ASUS Radeon 6850 1GB;
SSD Kingston hyperX 240GB; 30" HPZR30w monitor;
BeQuiet! E9 580W; http://www.the-nox.com

MrStein ::

kuall je izjavil:


sej lahko po insertu komot narediš preverbo, ali so vsi idji unique ali se je v tem času vrinil en drug isti id, če te tako skrbi, in javiš napako. ampak to je brezveze bluzeneje.

What the actual fuck?????

A to delaš neki prank? Vic?
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

jype ::

MrStein je izjavil:

What the actual fuck?????
Copy-paste programerji so najbolj kul.

dmok ::

korenje3 je izjavil:

Tako je kot si rekel, verjetno dodaja po kmečko.

Pa si upaš dodajati zapise v tabelo brez da se prepričaš kako točno oni povečujejo id ? Ker se lahko zgodi, da bo zaradi tvojih dodanih zapisov crknil njihov program.

MrStein ::

Zakaj sploh dodajaš zapise "mimo programa"?
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

Vazelin ::

Velika šansa je ja, da jim korenje zjebe in bazo in program:))
Lahko majo kako svojo tabelo s vrednostjo key-ev. To si pomislil, korenje? Sicer sem bolj sql noob (samo občasno zanima me), ampak igraš se nevarno igro
I got 99 problems but 2.5usd tezus ain't one.

Zgodovina sprememb…

  • spremenilo: Vazelin ()
«
1
2


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Učenje programiranja PHP

Oddelek: Programiranje
9673 (214) Spura
»

Potrebujem MySQL ukaz

Oddelek: Programiranje
121583 (1191) zvmk
»

[SQL] Insert

Oddelek: Programiranje
251518 (1120) greentech
»

[T-SQL] Kako vnest podatek v bazo in da ti hkrati vrne id?

Oddelek: Programiranje
161970 (1688) dmok
»

mySQL(+php) auto_increment field v tabeli.. Kako...?

Oddelek: Izdelava spletišč
6704 (636) Zvonko

Več podobnih tem