Avatar billede Droa Seniormester
17. december 2014 - 22:45 Der er 6 kommentarer og
1 løsning

hente id fra 2 tabeller som kan bruges i en mange til mange tabel

Hej eksperter.

Så jeg har 3 tabeller.

tabel_artikler
tabel_tags
artikler_tags - mange til mange relationer mellem artikler og tags

tabellerne indeholder en masse kolonner, men lige pt, skær jeg dem ned til hvad spørgsmålet handler om, for ikke og forvirre.


tags indeholder id (int, auto increment,primary), name (varchar(255),unique)
artikler indeholder id (int, auto increment,primary)
artikler_tags indeholder artikel_id (int), tag_id (int) med et index (artikel_id,tag_id (unique)

altså en ganske normal mange til mange relations tabel skema.

lige pt, så når der bliver lagt en ny artiekl op, så laver jeg en INSERT INTO på artiekl og tags, hvor jeg lidt dovent bruger on duplicate til at ignorere tags der allerede findes, så jeg kun skal bruge 2 sql sætninger dertil.

nu kommer det så til relations tabellen, hvor jeg skal bruge id'erne fra artikel og tags tabellen, de bliver jo oprettet på insert into, så jeg kender ikke til dem i min kode, med mindre jeg først henter dem.

lige pt, henter jeg dem ved og spørge efter dem med 2 select queues, for at jeg kan lave insert into's til artikler_tags.

findes der ikke en måde, hvor jeg istedet kan hente dem, i samme sql sætning, jeg laver mine relationer? så jeg kan få reduceret koden?


foreach($tags as $tag){
$sql = "INSERT INTO artikler_tags (artikel_id,tag_id) VALUES(SELECT id FROM tags WHERE name=$tag LIMIT 1,SELECT id FROM artikler ORDER BY id desc LIMIT 1)

}

eller noget i den stil, jeg har ikke kunne finde nogen gode svar på nettet desvære, så håber jeg kan få et her, på forhånd tak.
Avatar billede arne_v Ekspert
18. december 2014 - 03:28 #1
Jeg tror ikke at der er en super smart loesning paa problemet.

Jeg ville nok lave:

INSERT INTO artikler
x = SELECT LAST_INSERT_ID()
loop {
    INSERT INTO tags
    INSERT INTO artikler_tags x and SELECT FROM tags
}

Men det goer ikke den store forskel.
Avatar billede arne_v Ekspert
18. december 2014 - 03:33 #2
En anden mulighed er at droppe auto_increment og generere PK's i applikationen.

http://php.net/manual/en/function.uniqid.php

Saa er INSERT jo lige ud af landevejen.

Men du faar saa VARCHAR ikke INTEGER PK's.
Avatar billede Droa Seniormester
18. december 2014 - 05:07 #3
arhh ja mange tak for ideen, så går jeg så ud fra jeg lige skal tjekke for dublet errors, hvis nu man er uheldig at id'et er taget i forvejen, og generere et nyt uniqid?

hmm, jeg havde os lidt en tanke om at bruge en MD5 eller SHA på selve artiklens tekst+dato og generere et uniq id ud fra den, for at være sikker på det var uniqt, men er det en god ide?

lige et spørgsmål omkring "INSERT INTO artikler_tags x and SELECT FROM tags"


hvordan vil denne sætning se ud, hvis jeg ville bruge den? kan man godt bruge select i en into? for det er os lidt det jeg fisker lidt efter og finde ud af hvordan man gør.

sidst jeg arbejdede i mySQL, var da det hed version 3, så det er begrænset hvor meget jeg kender til det mere
Avatar billede Droa Seniormester
18. december 2014 - 05:19 #4
jeg tror jeg fandt en løsning, jeg fandt et mySQL syntax der hedder INSERT INTO SELECT



INSERT INTO test (id1,id2)
SELECT id,200 FROM forumtags where Tagname='Part'


den kopiere åbenbart ens select in i ensinsert into, så hvis den har flere  rækker, bliver ens select udført flere gange, men det burde den så ikke :)


200 kan så skiftes ud med ens artikel id, eller man kan jo os lave en LAST_INSERT_ID()


INSERT INTO test (id1,id2)
SELECT id,LAST_INSERT_ID()  FROM forumtags where Tagname='Part'


mange tak for hjælpen, tror jeg lige vil kigge på dine ideer, og måske bare vælge og bruge et php genereret uniq id, da jeg ikke er så meget for at bruge last-id, f.eks hvis noget har kørt på kryds af ens script.
Avatar billede Droa Seniormester
18. december 2014 - 05:34 #5
her er min fulde fungerende kode, for god ordens skyld.


static function AddForumLink(ThreadListEntity $entity) {
        if (self::$connected) {

            $sql = sprintf("INSERT INTO forumlinks (Threadid,Started,Scanned) VALUES('%s',%d,%d) ON DUPLICATE KEY UPDATE Scanned=Values(Scanned)", $entity->Link, $entity->Started, $entity->Scanned);
            self::$conn->query($sql);

            if (count($entity->Tags) > 0) {
                foreach ($entity->Tags as $tag) {
                    $sql2 = sprintf("INSERT IGNORE INTO forumtags (Tagname) VALUES('%s')", $tag);
                    self::$conn->query($sql2);
                    self::CheckForError();


                    $sql3 = sprintf("INSERT IGNORE INTO tagslinks (tagid,threadid) SELECT id,%d FROM forumtags where Tagname='%s'", $entity->Link, $tag);
                    self::$conn->query($sql3);
                    self::CheckForError();
                }
            }

            self::CheckForError();
        } else {
            echo "Error!: not connected to db\r\n";
        }
    }
Avatar billede Droa Seniormester
12. september 2015 - 19:54 #6
ligger du et svar?
Avatar billede arne_v Ekspert
13. september 2015 - 02:08 #7
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester