Avatar billede steen-h Mester
06. maj 2016 - 09:50 Der er 16 kommentarer og
1 løsning

Prepared Statements ORDER BY

Jeg har et problem med ORDER BY

Følgende kode giver op til 2 output, jeg bruger kun den ene.

[code]
if ($dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato ASC") ){
      $dobbel->bind_param('i', $dato);
      $dato = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));
      $dobbel->execute();
      $dobbel->bind_result($id, $numberofrows);
      $dobbel->fetch();
      $dobbel->close();

      if ($numberofrows > 1){
        if ($update = $mysqli->prepare("UPDATE ".$vtabel." SET ny=10 WHERE id=?")) {
          $update->bind_param('i', $id);
          $update->execute();
          $update->close();
      }
      echo "tabel ".$vtabel." id ".$id." dobbel <br>";
    }
  }

[/code]

Den jeg opdatere skal være den nyeste, men der er ikke forskel om jeg bruger
[code]
$dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato ASC
[/code]
eller
[code]
$dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato DESC
[/code]

Hvad gør jeg galt ?
Avatar billede steen-h Mester
06. maj 2016 - 09:51 #1
Nu fik jeg ikke lavet den blå box til koden, hvordan gør jeg det ?
Avatar billede michael_stim Ekspert
06. maj 2016 - 09:56 #2
div i stedet for code
Avatar billede steen-h Mester
06. maj 2016 - 10:04 #3
Tak
Avatar billede steen-h Mester
06. maj 2016 - 10:04 #4
Prepared Statements ORDER BY
Jeg har et problem med ORDER BY

Følgende kode giver op til 2 output, jeg bruger kun den ene.


if ($dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato ASC") ){
      $dobbel->bind_param('i', $dato);
      $dato = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));
      $dobbel->execute();
      $dobbel->bind_result($id, $numberofrows);
      $dobbel->fetch();
      $dobbel->close();

      if ($numberofrows > 1){
        if ($update = $mysqli->prepare("UPDATE ".$vtabel." SET ny=10 WHERE id=?")) {
          $update->bind_param('i', $id);
          $update->execute();
          $update->close();
      }
      echo "tabel ".$vtabel." id ".$id." dobbel <br>";
    }
  }



Den jeg opdatere skal være den nyeste, men der er ikke forskel om jeg bruger

$dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato ASC

eller

$dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato DESC


Hvad gør jeg galt ?
Avatar billede olsensweb.dk Ekspert
06. maj 2016 - 11:11 #5
#1
http://www.eksperten.dk/guide/1325
som michael_stim også skrev i #2

personligt bruger jeg altid
(div)(pre) (/pre)(/div)
for også at få en scroll bar i bunden

Husk at erstatte alle ( med [ og alle ) med ]




>Følgende kode giver op til 2 output, jeg bruger kun den ene.
du kunne vel bruge LIMIT

>if ($numberofrows > 1){
dette vil kun blive udført hvis der er flere rækker, men du vil kun opdaterer 1 række.

noget ala (utested)

if ($dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato ASC LIMIT 1") ){
    $dobbel->bind_param('i', $dato);
    $dato = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));
    $dobbel->execute();
    $dobbel->bind_result($id, $numberofrows);
    $dobbel->fetch();
    $dobbel->close();

    if ($numberofrows == 1){
        if ($update = $mysqli->prepare("UPDATE ".$vtabel." SET ny=10 WHERE id=?")) {
            $update->bind_param('i', $id);
            $update->execute();
            $update->close();
        }
        echo "tabel ".$vtabel." id ".$id." dobbel <br>";
    }
}
Avatar billede olsensweb.dk Ekspert
06. maj 2016 - 11:31 #6
jeg tror lige du må forklare hvad er det du vil opnå ??

ønsker du at finde alle dubletter ??
hvis ja:
    hvad skal der ske med disse ??
    hvad hvis der er mere end 2 af en slags

kan du ikke lave et sql dump af en test tabel
Avatar billede steen-h Mester
06. maj 2016 - 11:57 #7
Jeg indsætter noget data i en tabel en gang i døgnet, de kommer fra et gsm modul, normalt kommer de kl 5.01 men kan være forsinket.
Når de indsættes  er ny=0
Under test kan det ske flere gange.

Hver time 5 minutter over hel kører jeg et cronjob som opdatere nye rækker.
Når rækken er opdateret er nu=1
Der har jeg en function som tjekker for flere rækker samme dag, de fjernes ved at sætte ny=10

Jag kan selvfølgelig fjerne dubletter manuelt, men har en interesse i at det sker automatisk.
Avatar billede steen-h Mester
06. maj 2016 - 12:21 #8
Her er det jeg brugte inden jeg opdaterede til  Prepared Statements


while($r = mysql_fetch_array($veightlistsql)) {

  $tid = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));

  // tjek for dobbel vejning
  $dobbelsql = mysql_query("SELECT id FROM ".$r['tabel']." WHERE dato > ".$tid." AND ny = '1' ORDER BY dato DESC");

  if (mysql_num_rows($dobbelsql) > 1){
  $dobbel = mysql_fetch_array($dobbelsql);
  mysql_query("UPDATE ".$r['tabel']." SET ny=10 WHERE id = ".$dobbel['id']." LIMIT 1");
Avatar billede olsensweb.dk Ekspert
06. maj 2016 - 13:02 #9
>Her er det jeg brugte inden jeg opdaterede til  Prepared Statements
en quick fix til det er skruet sammen i Prepare Statement under mysqli er at opdaterer dit gamle script til mysqli Procedural style

(utested)

while($r = mysqli_fetch_array($veightlistsql)) {
  $tid = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));

  // tjek for dobbel vejning
  $dobbelsql = mysqli_query($mysqli, "SELECT id FROM ".$r['tabel']." WHERE dato > ".$tid." AND ny = '1' ORDER BY dato DESC");

  if (mysqli_num_rows($dobbelsql) > 1){
  $dobbel = mysqli_fetch_array($dobbelsql);
  mysqli_query($mysqli, "UPDATE ".$r['tabel']." SET ny=10 WHERE id = ".$dobbel['id']." LIMIT 1");
 

læg mærke til at alle mysql_xxx hedder mysqli_xxx dvs tilføjet et i
og du nu skal angive din connection ifm din query (  mysqli_query($mysqli, $sql) )

du er ikke tvunget til at bruge Prepare Statement under mysqli eller PDO, men du kan få nogle sikkerheds mæssige fordele, ved bruger indput

i mysqli kan du skrive 2 styles:
procedural style, som du kender fra det gamle mysql
oop style, dette er det der anvendes mest, og er fremtiden
du kan mixe de 2 style som du har lyst, men det er pænest at holde sig til 1 style.
Avatar billede steen-h Mester
06. maj 2016 - 16:22 #10
Jeg fik en opgave da jeg for nylig skiftede webhotel, det nye kørte php7 dog kunne det nedgraderes til php5.6.

Alle database indput er lavet med Prepare Statement, med stor hjælp fra dig ronols.
Som du skriver giver det mere sikkerhed og det er jeg glad for.

Men havde glemt muligheden med mysqli Procedural style.
Det jeg mangler at opdatere er mit cronjob, der er ingen input kun database kald, så der er mysqli Procedural style jo en ok løsning.

Læg et svar ronols
Avatar billede olsensweb.dk Ekspert
06. maj 2016 - 23:25 #11
svar
Avatar billede steen-h Mester
07. maj 2016 - 07:21 #12
Jeg har altså en fejl, her er koden
 
function dobbelvej($vtabel){

global $mysqli;

$vtabel = "veight_3";

echo "<br>".$vtabel." tabel<br><br>";
if ($dobbel = $mysqli->prepare("SELECT id, count(id) FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato DESC") ){
      $dobbel->bind_param('i', $dato);
      $dato = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));
      $dobbel->execute();
      $dobbel->bind_result($id, $numberofrows);

      while ($dobbel->fetch() ) {
        echo $id." id ".$numberofrows." number roads<br>";
}
      $dobbel->close();

}
 
}

Og output, der står der er 3 tabeller men der laves kun et gennemløb ?
 
veight_3 tabel

62 id 3 number roads


Her er sql dump ad de 3 rækker
 
-- phpMyAdmin SQL Dump
-- version 4.6.1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: May 07, 2016 at 05:13 AM
-- Server version: 5.6.29
-- PHP Version: 5.6.18

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `test_db`
--

-- --------------------------------------------------------

--
-- Table structure for table `veight_3`
--

CREATE TABLE `veight_3` (
  `id` bigint(20) NOT NULL,
  `dato` int(11) DEFAULT NULL,
  `kg` decimal(6,2) DEFAULT NULL,
  `forandring` decimal(6,2) DEFAULT NULL,
  `bat` decimal(3,2) DEFAULT NULL,
  `ny` tinyint(1) DEFAULT '0',
  `cronjob` tinyint(1) DEFAULT '0',
  `tempint` decimal(6,2) NOT NULL,
  `tempext` decimal(6,2) NOT NULL,
  `timevej` tinyint(1) NOT NULL DEFAULT '0',
  `bit` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `veight_3`
--

INSERT INTO `veight_3` (`id`, `dato`, `kg`, `forandring`, `bat`, `ny`, `cronjob`, `tempint`, `tempext`, `timevej`, `bit`) VALUES
(62, 1462593675, '0.00', '0.00', '0.00', 1, 1, '0.00', '0.00', 0, 0),
(63, 1462593680, '0.00', '0.00', '0.00', 1, 1, '0.00', '0.00', 0, 0),
(64, 1462593685, '0.00', '0.00', '0.00', 1, 1, '0.00', '0.00', 0, 0);

--
-- Indexes for dumped tables
--

--
-- Indexes for table `veight_3`
--
ALTER TABLE `veight_3`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `veight_3`
--
ALTER TABLE `veight_3`
  MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=65;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Avatar billede steen-h Mester
07. maj 2016 - 07:24 #13
Jeg mente selvfølgelig 3 rækker

veight_3 tabel

62 id 3 number roads
Avatar billede steen-h Mester
07. maj 2016 - 09:24 #14
Hvis jeg fjerner count(id) får jeg alle rækker
 
if ($dobbel = $mysqli->prepare("SELECT id FROM ".$vtabel." WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato DESC") ){
      $dobbel->bind_param('i', $dato);
      $dato = mktime(0, 0, 0, date("m",time())  , date("d",time()), date("Y",time()));
      $dobbel->execute();
      $dobbel->bind_result($id);
    while ($dobbel->fetch() ) {
        echo $id." id <br>";
}
      $dobbel->close();

Output
 
64 id
63 id
62 id
Avatar billede olsensweb.dk Ekspert
07. maj 2016 - 11:44 #15
#14
>Hvis jeg fjerner count(id) får jeg alle rækker
fandt jeg også ud af, så er vi jo nok tilbage i mysqli_stmt_num_rows igen
http://php.net/manual/en/mysqli-stmt.num-rows.php
som vi ellers lavede om i http://www.eksperten.dk/spm/1010482

men din code må så se sådan ud:
 
<?php

function dobbelvej($vtabel) {

    global $mysqli;

    // $vtabel = "veight_3"; // kommer som parameter
    echo "<br>" . $vtabel . " tabel<br><br>";

    if ($dobbel = $mysqli->prepare("SELECT id FROM " . $vtabel . " WHERE dato > ? AND (ny = '1' OR ny = '3') ORDER BY dato DESC")) {
        $dobbel->bind_param('i', $dato);
        $dato = mktime(0, 0, 0, date("m", time()), date("d", time()), date("Y", time()));


        $dobbel->execute();
        // bind selected values
        $dobbel->bind_result($id);
        /* store result to use num_rows */
        $dobbel->store_result();

        $numberofrows = $dobbel->num_rows;

        echo $numberofrows . "<br>"; // test

        if ($numberofrows > 0) {
            while ($dobbel->fetch()) {
                echo $id . " " . $numberofrows . "<br>";
            }
        }
        else{
            echo "Ingen rækker fundet";
        }
        $dobbel->close();
    }
    else{
        echo "fejl i sql";
    }
}

$mysqli = new mysqli("localhost", "root", "", "test");
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

dobbelvej("veight_3");
?>



>global $mysqli;
jeg er imod brugen af global, jeg ville tage værdien over som parameter


så dette 
dobbelvej("veight_3");
function dobbelvej($vtabel)

laves om til
dobbelvej($mysqli, "veight_3");
function dobbelvej($mysqli, $vtabel)

og så slette global $mysqli
Avatar billede steen-h Mester
08. maj 2016 - 10:05 #16
#15
Ja med
$numberofrows = $dobbel->num_rows;
virker det fint.

jeg vil følge dit råd med ikke at bruge globale variabler.
Avatar billede arne_v Ekspert
29. maj 2016 - 04:47 #17
Skal $numberofrows bruges sammen med $id?

Hvis ikke saa ville jeg erstatte:

        $dobbel->store_result();
        $numberofrows = $dobbel->num_rows;
        if ($numberofrows > 0) {
            while ($dobbel->fetch()) {
                echo $id . " " . $numberofrows . "<br>";
            }
        }
        else{
            echo "Ingen rækker fundet";
        }

Med:

        while ($dobbel->fetch()) {
            echo $id . "<br>";
        }
        $numberofrows = $dobbel->num_rows;
        if ($numberofrows == 0) {
            echo "Ingen rækker fundet";
        }
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