Avatar billede simsen Mester
29. august 2010 - 20:19 Der er 15 kommentarer og
1 løsning

Delete med triggers

Hejsa,

Jeg er først lige ved at lære triggers, så bær over med mig, hvis det er et tumpet spørgsmål :-)

Jeg har følgende trigger:

ALTER TRIGGER [dbo].[deletePollCommentsTrigger]
  ON  [dbo].[Poll_Comments]
  FOR DELETE
AS
BEGIN
    DECLARE @intRowCount int
    SELECT @intRowCount = @@RowCount
    IF @intRowCount > 0
    BEGIN
        DELETE Activity_Log WHERE id IN (SELECT questionId FROM deleted) AND
            activityDateCreated IN (SELECT commentsCreateDate FROM deleted) AND activitySectionPId = 8
    END
END

Det den skulle var at slette en række i Activity_Log - hvis id = questionId og activityDateCreated = commentsCreateDate og activitySectionPId = 8

Det gør den så bare ikke
Mine rækker:
Poll_Comments:
questionId = 31 commentsCreateDate = 29-08-2010 19:48:38

Activity_Log:
id = 31 activityDateCreated = 29-08-2010 19:45:27 activitySectionPid = 8
id = 31 activityDateCreated = 29-08-2010 19:48:38 activitySectionPid = 8

Altså den skulle så når jeg sletter rækken i Poll_Comments slette rækken med samme dato og klokkeslet i Activity_Log...Men som sagt - det gør den ikke....

Hvis jeg istedet skriver følgende:

DELETE Activity_Log WHERE id IN (SELECT questionId FROM deleted) AND activitySectionPId = 8

Sletter den korrekt begge linjer i Activity_Log - men jeg er så kun interesseret i, at den sletter den ene - derfor vil jeg også test på dato/klokkeslet.

Nogen idé til hvordan jeg gør dette?

mvh
simsen :-)
Avatar billede Syska Mester
29. august 2010 - 20:37 #1
Bruger ikke triggers ... de er i min verden smarte nok, men svære at debug, som du arbejder på nu :-)

Hvis du ved hvad du vil slette, hvorfor så ikke lave en SP til det eller skriver alt den sql der skal til for at gøre det ?

eller

Hvis det er alle child rows i en anden table som skal slettes, kan du på din Foreign Key sætte Cascade Delete ... så sletter den automatisk de tilhørende rows.

mvh
Avatar billede simsen Mester
29. august 2010 - 20:47 #2
Hej buzzzz,

Jeg ved ikke hvad jeg vil slette, idet jeg ikke kender hverken id eller dato/klokkeslet - jeg kender kun commentsId som jeg så sletter på i Poll_Comments.....

Det er jo her triggers skulle være smarte - og er de også, når jeg altså vil slette alle rækker - men vil kun slette den ene række *griner*
Avatar billede Syska Mester
29. august 2010 - 20:56 #3
Nogen må vel sætte det delete igang ... :-) og deraf kende ID.

Kan du ikke sætte nogen "print" sætninger ind i din delete ... og så prøve at lave lidt select og så udskrive de værdier ... for du jo få et forkert resultat ... siden den ikke sletter de rows.

Men hvordan er det bygget op ... lyder mere som om du bare burde slå "Cascade delete" til på din "Foreign key"

mvh
Avatar billede simsen Mester
29. august 2010 - 21:18 #4
Det er ikke en foreign key...... det er kun en kolonne, jeg har sat ind, for at holde styr på, hvilken Poll Question/EventId osv (og nej, den er ikke altid udfyldt, da der også kommer ting ind i den tabel, hvor der ikke er en id), der er tale om....

Og jo - jeg kan gå den gammeldags vej, der tager en fandens masse ressourcer....

Når jeg sletter en række i Poll_Comments - slå op først i Poll_Comments for at hente den pågældende række ud, jeg vil slette - med de værdier jeg så har - så at slette rækken i Activity_Log........men igen - det bliver mega mange ressourcer - for det skal ikke kun ske for Poll_Comments - men for stort set samtlige tabeller i databasen.......

Det er ikke løsningen for mig..... Så hælder jeg mere til, at brugerne får en "Siden kan ikke vises" - når de forsøger at klikke på det link, som vises for den pågældende række.
Avatar billede Syska Mester
29. august 2010 - 21:27 #5
Triggers er den gammel dags vej ... de er nere resourse krævende i forhold til selv at lave logikken som fjerner de rows du snakker om.

Jeg ville nok se på designet af din "Log" table og få integreret primary keys, ellers kan du let ende med en inkonsistent database ... hvis eneste måde at slå op i den er via en "Poll".

Det hele kan laves som 2 quries(2 stk delete) du skal køre mod din DB. Det synes jeg ikke er specielt meget. På den måde har du også alt logikken i din kode, og ikke i din database.

mvh
Avatar billede simsen Mester
29. august 2010 - 21:52 #6
Nu bliver jeg lidt nysgerrig - hvordan vil du lave en primary key på Activity_Log tabellen....

I den har jeg følgende kolonner
logId, UserId, activitySectionPId, id, activityUrl, activityDateCreated, title (og lidt flere)

Som navnet siger - så er det en aktivitets tabel - der registrerer stort set alt aktivitet, der foregår i de andre tabeller.....

Altså når jeg indsætter en ny afstemning - så smider jeg
UserId, activitySectionPId, id (som i det her tilfælde er id i Poll tabellen). Når jeg indsætter en ny bruger i tabellen, sætter jeg UserId, activitySectionPId, id (som i det her tilfælde bliver 0, da jeg jo bruger UserId), activityUrl, osv. ind. Når jeg indsætter en begivenhed, sker der det samme igen....

Og her har jeg bare nogle få beskrevet, af de aktiviteter, jeg indsætter......Du vil så have, jeg laver en ny kolonne for hver enkelt aktivitet:

For ny afstemning questionId
For ny kommentar til afstemning pollCommentId
osv?

Det bliver godt nok mange rigtig mange 0'er jeg skal sætte ind i databasen, for hver gang jeg laver en insert (og jo, jeg bruger den stort set konstant) til den ene tabel....

Og selvfølgelig har jeg én primary key .......logId og nej - den er ikke sat ind i Poll_Comments - da jeg opretter Poll_Comments før jeg opretter aktiviteten (ikke smart at oprette en aktivitet, hvis der sker en fejl i oprettelsen af kommentaren *griner*)...

Så ville jeg igen skulle oprette f.eks. en kommentar i Poll_Comments - få id ud - oprette en aktivtet - få id ud og så opdatere Poll_Comments med den aktivitet.....heller ikke smart -igen unødig ressource forbrug...
Avatar billede Syska Mester
29. august 2010 - 22:24 #7
Kig på det her ... burde give en ide om det.
http://img812.imageshack.us/i/capturewsd.png/

Log table
LogID er bare identity.
ID er hvad den skal joine på i den table den tilhører.
Type er hvad Type log det er. ( Poll eller News )

Håber det giver mening.

mvh
Avatar billede simsen Mester
29. august 2010 - 22:35 #8
buzzz

Så er jeg ikke helt ved siden af - for sådan jeg gør det *griner* Min activitySectionPId er lig med din Type

Mit problem er så mine kommentar tabeller.....

f.eks. Poll_Comments som har følgende....
commentsId,
pollId,
createDate,
comment

Når jeg opretter i Activity_Log kender jeg kun til pollId ikke til commentsId - ergo så er id PollId og ikke commentsId....

Og mens jeg skriver det her - så overvejer jeg lige om, jeg ikke rent faktisk kender commentsId, når jeg opretter kommentaren.... Vender lige frygtelig tilbage ommelet.....

En anden ting, jeg registrerer på dit billede - skriver du alle feltnavne med stort begyndelsesbogstav - I tidernes morgen lærte jeg, at de skulle være med lille og tabel navne med stort - ved godt det er en smagssag - men er det ikke længere kotume?
Avatar billede Syska Mester
29. august 2010 - 22:43 #9
Jeg har min database i samme navgivning som .NET C# bruger ... men det er nok en smagssag som du selv skriver :-)

Du kender CommentID efter du har oprettet den i database, før kan du ikke kende den ... hvis det er en identity.

Husk at bruge transcations ... så der ikke bliver commited noget, hvis en af dine sql statements fejler ... så vil du ikke opleve at der ikke er en log til en comment.

Og jeg har lige fundet et problem i min løsning ... vender tilbage igen.
Avatar billede simsen Mester
29. august 2010 - 22:48 #10
hmmmmm kan se, jeg godt kan hitte ud af at hente commentsId ud - kræver lidt om programmering......men ikke så meget, da det kun er comments det er galt med for de forskellige tabeller - så kun en 5-6 steder......vil jeg gøre og så stadig bruge mine triggers uden dato....

Tak for hjælpen og smid dit svar :-)
Avatar billede simsen Mester
29. august 2010 - 22:52 #11
Jeg bruger transactions......men har også lært, at så få ting som muligt i mine sql ting - altså åbn database - gør DIN (i éntal) ting - luk....

Det vil sige - det jeg gør er at:

åbn database
insert comment
luk database

åbn database
insert activity
luk database

Jeg HAR fået rap over fingrene for at lave flere ting i en sql statement - det tør jeg squette igen *griner*
Avatar billede Syska Mester
29. august 2010 - 22:59 #12
Fordi du kalder Close, så er den stadig åben i .NET, google "sql .net connection poling" mener jeg det hedder.

Jeg er dog lidt i tvivl om du må lukke din connection, hvis du bruger transactions. ( virker ikke logisk i min verden )

Men hvor er din transaction i overstående ?

mvh og svar
Avatar billede Syska Mester
29. august 2010 - 23:00 #13
Korrekt at du ikke unødigt bør holde en connection åben længere end nødvendig, men arbejdet skal jo udføres :-)
Avatar billede simsen Mester
29. august 2010 - 23:12 #14
Den ligger i min insert, og ligger incl. i DBUtility class f.eks den her:

public int ExecuteScaler(string query, CommandType commandtype)
        {
            object identity = 0;
           
            try
            {
                _command.CommandText = query;
                _command.CommandTimeout = _commandTimeout;
                _command.CommandType = commandtype;

                if (_connection.State == System.Data.ConnectionState.Closed)
                {
                    _connection.Open();
                }

                _command.Connection = _connection;

                BeginTransaction();

                identity = _command.ExecuteScalar();             
            }
            catch (Exception)
            {
                RollbackTransaction();
                throw;
            }
            finally
            {
                CommitTransaction();
                _command.Parameters.Clear();

                if (_connection.State == System.Data.ConnectionState.Open)
                {
                    Dispose();
                }
            }

            return Convert.ToInt32(identity);
        }
Avatar billede Syska Mester
29. august 2010 - 23:21 #15
finally bliver da altid kaldt ... så mon ikke din commit skal op i din try ? ( eller sover min hjerne )

Du bør måske også kun catch Sql Expcetions ... men det andet virker selvf også.
Avatar billede simsen Mester
29. august 2010 - 23:36 #16
*Du har ret.....

Den ligger der kun indtil, jeg har fået ryddet liiiiiidt mere op - der skal være en connection close (den ligger lige pt i Commit) i finally istedet....
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
Kategori
Computerworld tilbyder specialiserede kurser i database-management

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



IT-JOB

Gehl Architects ApS

IT Supporter

Sparekassen Danmark

RPA-udvikler til IT-afdelingen

Saab Danmark A/S

Senior Software Developer

Udviklings- og Forenklingsstyrelsen

Controller til økonomi og compliance