Gå til innhold

Anbefalte innlegg

Sliter litt med å endre en enkel variabel i en mysql database. Har stort sett drevet med fil systemer, og ikke mysql, så er ikke kommet helt inn i "gamet".

 

$sth = $dbh->prepare("update items set tilbakelevert=true where nummer=$nummer") or &feilmelding;

 

$sth->execute("$ar-$maned-$dag") or &feilmelding;

 

Har en liste over diverse utstyr som kan lånes ut, og skal oppdatere variabelen som tilsier om utstyret er tilbakelevert. Dette i form av en dato. Format yyyy-mm-dd

 

Får denne feilmeldingen:

 

DBD::mysql::st execute failed: called with 1 bind variables when 0 are needed at tilbakelevering.cgi line 86.

 

Linje 86 er altså den siste av de to vist ovenfor.

 

Kanskje litt vanskelig å si hvorfor det ikke fungerer på grunnlag av det lille jeg postet av koder, så kan kanskje poste hele scriptet hvis det er nødvendig?

 

 

Takk for evt. svar.

Lenke til kommentar
Videoannonse
Annonse

Du har ikke definert bind-variblen din riktig.

 

$sth = $dbh->prepare("update items set tilbakelevert=true where nummer=$nummer") or &feilmelding;

$nummer er feil, det skulle vært :nummer om jeg ikke husker feil, men se på DBI-manualen om bind variabler, det er rimelig enkelt når man bare har forstått hvordan...

;)

Si ifra om du ikke blir noe klokere, jeg kan grave opp nøyaktig hva du skal gjøre.

 

M.

 

PS, et av de store debuggingstipsene: 99% av alle feil som rapportere skyldes noe du har gjort feil på en tidligere linje...

Lenke til kommentar

Feilmeldingen sier mye. Du forsøker å bruke bind-variabler uten at du har satt opp noen i prepare statement. Med DBI har en muligheten til å lage SQL prepare statement hvor en fyller inn en variabel idet spørring kjøres (executes). Dette gjør at statement kan kjøres flere ganger uten at det trengst å "prepare'es" på nytt.

 

Tror ikke du har behov for dette.

 

Bare rett på SQL'en slik at du også sjekker for dato i spørring og deretter kjør en

 

$sth->execute();

 

så skulle det være i boks.

Endret av trtrtr
Lenke til kommentar

Tror ikke jeg skjønte helt, siden det virker som dere har to forskjellige svar på dette.

 

Mysjkin, du sier at $nummer er feil? Dette skjønner jeg ikke, siden jeg skal finne den linja som inneholder $nummer.

 

Og trtrtr, hvordan kan jeg sjekke datoen i spørringen? Det jeg skal gjøre er erstatte den, hvordan kan jeg gjøre dette i SQL'n?

 

Beklager at jeg er treg, men har nix erfaring med perl + mysql.

Takk for svar da! :)

Lenke til kommentar

Mulig jeg misforstod litt hva du prøver å gjøre i SQL'en. Hvor henter du info om utstyr er tilbakelevert eller ikke? Hva slags data har du tilgjengelig og hva slags kolonner er det du vil oppdatere basert på dette?

 

Et tips for å enklere få dette til er å logge inn på databasen via console, teste med select..where-SQL helt til du er sikker på at du velger ut rader med rett data, deretter benytte dette sammen med update.

Lenke til kommentar

Kan prøve og forklare.

Jeg har to tabeller. En med liste over utstyret som kan lånes ut, og en der utlånene legges inn.

Det som skjer, er at når noen låner nå, så trekkes det fra utstyrslista, og det legges inn hvor mange ting som er lånt i den andre tabellen.

Men når jeg skal levere tilbake noe, så åpner jeg utstyrstabellen, plusser på det som er tidligere lånt, og så skal jeg legge inn en dato til utlåneren som sier når det er tilbakelevert.

 

Utstyrslista inneholder:

xbox, kontrollere, gigabit, switch, nettverkskabler og spill.

 

Lånerlista inneholder:

Navn, lånedato, leveredato, xbox, kontrollere, gigabit, siwtch, nettverkskabler, spill og tilbakeleveringsdato.

 

 

Dette er det første som kjøres:

$sth = $dbh->prepare("replace into utstyrstatus(xbox, kontrollere, gigabit, switch, nettverkskabler, spill) values(?,?,?,?,?,?)") or &feilmelding;

$sth->execute($xboxstatus,$kontrollerestatus,$gigabitstatus,$switchstatus,$nettverkskablerstatus,$spillstatus) or &feilmelding; 

 

Så kommer den biten jeg viste til dere.

Får det ikke helt til å stemme, så hadde vært kjekt med litt hjelp.

Lenke til kommentar

Beklager, som jeg sa, jeg husket ikke nøyaktig syntaks... Blandet sammen med delphi... :blush:

 

Du definerer en bind-variabel med å sette inn ?, ikke et variabelnavn som du hadde gjort i det første eksemplet, med andre ord,

$sth = $dbh->prepare("update items set tilbakelevert=true where nummer=?") or &feilmelding;
$sth->execute("$ar-$maned-$dag") or &feilmelding; 

Skal fungere, argumentene til execute blir satt inn der ? er i SQLen i prepare.

 

Alternativt kan du sette dataene rett inn i sql-setningen og kjøre execute uten argumenter da får du:

$sth = $dbh->prepare("update items set tilbakelevert=true where nummer=\"$ar-$maned-$dag\"") or &feilmelding;
$sth->execute() or &feilmelding; 

 

Du har i hvert fall tre fordeler med bind variabler:

1) Dersom du skal kjøre samme query (med mulig forskjellige argumenter), går det mye kjappere

2) Du slipper å escape anførselstegn

3) Du er garantert å unngå sql-injection bevisst eller ved uhell. Dersom variablen du kjører blir lik "null; drop table items" kan du jo gjette hva som skjer....

 

Dersom du i løpet av et program bare skal kjøre en spørring en gang og har kontroll over inputen, kan du bygge opp sql-en direkte, men jeg pleier alltid å bruke bind-variabler, plutselig vokser programmet utover det man opprinnelig forutså.... (litt det samme som use strict;...)

 

Håper det er klarere nå.

 

M.

Lenke til kommentar

Fungerte! Fikk ingen feilmelding, men ingenting endret seg i tabellen. Underlige greier.

Tror kanskje jeg poster hele scriptet her. Kanskje noe gidder å kommentere litt til.

Finner ikke noen gode tutorials på dette, og siden jeg ikke har tenkt å bruke dette så ekstremt mye mer enn til dette, så vil jeg ikke bruke penger på en bok om perl og mysql.

 

#!/usr/bin/perl

use DBI;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
require "variabler.pl";  
require "subroutines.pl";  

# Koble til databasen.
$dbh = DBI->connect( "dbi:mysql:database", "bruker", "passord", { RaiseError => 1, AutoCommit => 1}) or feilmelding("Kan ikke koble til:",$dbh->errstr);

&sendform;
print "Content-type:text/html\n\n";

# Hente formskjemaet
$nummer = $FORM{'nummer'};
$ar = $FORM{'ar'};
$dag = $FORM{'dag'};
$maned = $FORM{'maned'};

$nydato = "$ar-$maned-$dag";

# Få tak i utlånsinformasjonen til det aktuelle elementet

my($sth) = $dbh->prepare("select * from items where nummer=$FORM{'nummer'} order by nummer") or feilmelding("Kan ikke velge fra tavle: ",$dbh->errmsg);
my($rv) = $sth->execute;
my($f);
while ($f = $sth->fetchrow_hashref) {


$navn = $f->{navn}; 
$dato = $f->{dato};
$levere = $f->{levere};
$xbox = $f->{xbox}; 
$kontrollere = $f->{kontrollere};
$gigabit = $f->{gigabit};
$switch = $f->{switch};
$nettverkskabler = $f->{nettverkskabler}; 
$spill = $f->{spill}; 
$tilbakelevert = $f->{tilbakelevert};
}

# Hente utlånsstatus informasjonen
my($sth) = $dbh->prepare("select * from utstyrstatus order by xbox") or feilmelding("Kan ikke velge fra tavle: ",$dbh->errmsg);
my($rv) = $sth->execute;
my($f);
while ($f = $sth->fetchrow_hashref) {
if ($xbox == 1 ) { $xboxstatus == 1; } 
$kontrollerestatus = $f->{kontrollere} + $kontrollere;
$gigabitstatus = $f->{gigabit} + $gigabit;
$switchstatus = $f->{switch} + $switch;
$nettverkskablerstatus = $f->{nettverkskabler} + $nettverkskabler;
$spillstatus = "0";
}

# Hvis xboxen er utlånt, lever tilbake
if ($xboxstatus == 1) {
$sth = $dbh->prepare("replace into utstyrstatus(xbox, kontrollere, gigabit, switch, nettverkskabler, spill) values(?,?,?,?,?,?)") or &feilmelding;

$sth->execute($xboxstatus,$kontrollerestatus,$gigabitstatus,$switchstatus,$nettverkskablerstatus,$spillstatus) or &feilmelding; 
} else { 
# Hvis noen andre låne xboxen, ikke gjør noe med det. 
$sth = $dbh->prepare("replace into utstyrstatus(xbox, kontrollere, gigabit, switch, nettverkskabler, spill) values(xbox,?,?,?,?,?)") or &feilmelding;

$sth->execute($kontrollerestatus,$gigabitstatus,$switchstatus,$nettverkskablerstatus,$spillstatus) or &feilmelding;
}

# Endre på tilbakelevert datoen. 

$sth = $dbh->prepare("update items set tilbakelevert='true' where nummer=?") or &feilmelding;
$sth->execute("$ar-$maned-$dag") or &feilmelding;

 

Der var hele greia. Har en print beskjed på slutten, men lite vits at jeg poster den her.

Hvis noen hadde orket å hjelpe meg med dette hadde jeg vært takknemlig.

 

Et annet problem jeg får, er at istedet for å endre på utstyrslista, så lages det en ny linje med de riktige tallene. Jeg bruker replace, men det ser ikke ut til å fungere.

 

Takk.

Lenke til kommentar

Som nevnt tidligere:

 

 

Utstyrslista inneholder:

xbox, kontrollere, gigabit, switch, nettverkskabler og spill.

 

Lånerlista inneholder:

Navn, lånedato, leveredato, xbox, kontrollere, gigabit, siwtch, nettverkskabler, spill og tilbakeleveringsdato.

Lenke til kommentar

Når jeg kjører "show keys from utstyrstatus" i phpmyadmin, så får jeg fram ingenting. Bare en bekreftelse.

Beklager at jeg har så lite kunnskap på dette, men jeg er bortimot helt blank på databaser.

Er keys det samme som hvilke type felter som blir brukt? Altså int og text?

Lenke til kommentar

vel, angående replace:

http://dev.mysql.com/doc/refman/5.0/en/replace.html

 

mysql-manualen sier dette om replace queries:

REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.

 

du så selv at du ikke har noen keys (og da ei heller noen indekser) så replace vil aldri overskrive eksisterende data i din tabell.

Lenke til kommentar

Okey. Da klarner det litt. Skal prøve meg litt fram med å bruke update der, men er litt usikker på hvordan jeg skal klare å få det til slik jeg "har fått det til" nå. For jeg sjekker om xboxen er utlånt, og hvis den er det så leverer jeg den tilbake, hvis ikke så rører jeg ikke den variabelen. Men hvordan er dette mulig update? Sitter å studerer update informasjonen i doc'n, og tror kanskje jeg skjønner. Skal prøve meg litt fram, så forhåpentligvis får jeg det til selv.

 

Har fortsatt ikke skjønt hvorfor update ikke fungerte i det nederst tilfellet, men kanskje doc'en kan forklare dette.

Som sagt, skal prøve litt selv, men har du noe mer å tilføye, så tar jeg gjerne imot flere råd.

Kjempe bra så langt! Begynner å skjønne systemet nå.

Lenke til kommentar

Har laget en key på alle, unntatt spill, hvor dette ikke var mulig, og lagde ei ny linje hvor jeg la inn et nummer og gjorde denne til primary.

Hva nå. De har navn etter feltnavnet sitt. Altså xbox, kontrollere osv..

Hvordan kan jeg bruke dette i scriptet?

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...