Mysql Mobile Media Function


PHP offre tre diverse API per connettersi a MySQL. Questi sono i mysql (rimosso dal PHP 7), mysqli. e le estensioni PDO. Le funzioni mysql usato per essere molto popolare, ma il loro uso non è incoraggiata più. Il team di documentazione sta discutendo la situazione della sicurezza del database, ed educare gli utenti ad allontanarsi dalla estensione extmysql comunemente usato è parte di questo (controllare php. internals: extmysql ironico). E il team sviluppatore PHP in seguito ha preso la decisione per generare EDEPRECATED errori quando gli utenti si connettono a MySQL, sia attraverso mysqlconnect (). mysqlpconnect () o la funzionalità di connessione implicita integrata in extmysql. extmysql è stato ufficialmente deprecata come di PHP 5.5 ed è stata rimossa dal PHP 7. Quando si va in qualsiasi pagina di manuale funzione mysql, si vede una scatola rossa, spiegando che non deve più essere utilizzato. Allontanandosi dal extmysql non riguarda solo la sicurezza, ma anche di avere accesso a tutte le caratteristiche del database MySQL. extmysql è stato costruito per MySQL 3.23 e ottenuto solo pochissime aggiunte da allora, mentre la maggior parte mantenendo la compatibilità con questa vecchia versione, che rende il codice un po 'più difficile da mantenere. caratteristiche mancanti che non sono supportati dalla extmysql includono: (da manuale di PHP). Motivo per non utilizzare la funzione mysql: Non fase di sviluppo attivo Rimosso dal PHP 7 Manca un'interfaccia OO doesnt sostenere non bloccante, asincrono interroga supporto Doesnt preparato privacy o query con parametri procedure di supporto memorizzati pretende molto Doesnt supportano più istruzioni pretende molto le operazioni di supporto incaricato di tirare supportano tutte la funzionalità di MySQL 5.1 mancanza di supporto per le istruzioni preparate è particolarmente importante in quanto forniscono un, meno errori metodo incline più chiara di fuga e citando i dati esterni di fuga manualmente con una chiamata di funzione separata. Soppressione warning di deprecazione Mentre il codice viene convertito in MySQLi DOP. errori EDEPRECATED possono essere soppressi impostando errorreporting in php. ini per escludere EDEPRECATED: Si noti che questo sarà anche nascondere altri warning di deprecazione. che, tuttavia, può essere per altre cose oltre MySQL. (Da manuale di PHP) e un modo migliore è DOP. e ora sto scrivendo un semplice tutorial DOP. Un semplice e breve DOP esercitazione D. Prima domanda nella mia mente era: qual è DOP A. DOP PHP Data Objects è uno strato di accesso al database che fornisce un metodo uniforme di accesso a più database. Connessione a MySQL con la funzione mysql o possiamo dire che il vecchio modo (deprecato in PHP 5.5 e sopra) con DOP. Tutto quello che devi fare è creare un nuovo oggetto PDO. Il costruttore accetta parametri per specificare il costruttore della sorgente del database PDO s avviene per lo più quattro parametri che sono DSN (Data Source Name) e il nome utente opzionalmente. parola d'ordine . Qui penso che si ha familiarità con tutti tranne DSN questo è nuovo a DOP. Un DSN è fondamentalmente una serie di opzioni che raccontano DOP che driver da usare, e dettagli di connessione. Per ulteriori riferimenti, controllare MySQL DOP DSN. Nota: è anche possibile utilizzare charsetUTF-8. ma a volte causa un errore, per cui il suo meglio usare utf8. Se c'è un errore di connessione, sarà gettare un oggetto PDOException che può essere memorizzato nella cache per gestire un'ulteriore eccezione. È inoltre possibile passare a diverse opzioni del driver come un array per il quarto parametro. Vi consiglio di passare il parametro che mette DOP in modalità eccezione. Perché alcuni driver PDO dont sostenere istruzioni preparate nativi, in modo DOP esegue emulazione del preparare. Inoltre, consente di attivare manualmente questa emulazione. Per utilizzare le dichiarazioni preparate lato server native, si dovrebbe esplicitamente impostarlo falso. L'altro è quello di spegnere la preparazione di emulazione che viene abilitata nel driver di MySQL di default, ma preparare l'emulazione dovrebbe essere disattivata per utilizzare in modo sicuro DOP. Io poi spiegare perché preparare emulazione dovrebbe essere spento. Per trovare motivo si prega di controllare questo post. E 'utilizzabile solo se si utilizza una vecchia versione di MySQL che io non raccomandato. Di seguito è riportato un esempio di come si può fare: Possiamo impostare gli attributi dopo la costruzione DOP Sì. Possiamo anche impostare alcuni attributi dopo la costruzione DOP con il metodo setAttribute: Gestione degli errori La gestione degli errori è molto più facile in PDO rispetto a MySQL. Una pratica comune quando si utilizza MySQL è: o morire () non è un buon modo per gestire l'errore dal momento che non siamo in grado di gestire la cosa in die. Sarà solo alla fine dello script di colpo e then echo l'errore allo schermo, che di solito non si desidera mostrare agli utenti finali, e lasciare che gli hacker sanguinose scoprire lo schema. In alternativa, i valori di ritorno delle funzioni di MySQL possono spesso essere utilizzati in combinazione con mysqlerror () per gestire gli errori. DOP offre una soluzione migliore: eccezioni. Tutto ciò che facciamo con DOP deve essere avvolto in una prova - blocco catch. Siamo in grado di costringere DOP in una delle tre modalità di errore impostando l'attributo modalità di errore. Tre modalità di gestione degli errori sono al di sotto. PDO :: ERRMODESILENT. Il suo solo i codici di errore di impostazione e gli atti più o meno lo stesso di mysql in cui è necessario controllare ogni risultato e poi guardare db-gterrorInfo () per ottenere i dettagli dell'errore. PDO :: ERRMODEWARNING Raise EWARNING. (Avvertenze Run-time (errori non fatali). Esecuzione dello script non viene interrotta.) DOP :: ERRMODEEXCEPTION. Generare eccezioni. Esso rappresenta un errore sollevato dalla DOP. Si consiglia di non gettare un PDOException dal proprio codice. Vedere Eccezioni per ulteriori informazioni sulle eccezioni in PHP. Si comporta molto simile o die (mysqlerror ()). quando isnt catturato. Ma a differenza o morire (). il PDOException può essere catturato e gestito con grazia se si sceglie di farlo. E si può avvolgere in prova - cattura. come di seguito: Non c'è bisogno di gestire con prova - fermo al momento. Si può prendere in qualsiasi momento opportuno, ma vi consiglio vivamente di utilizzare try - catch. Inoltre può avere più senso per prenderlo al di fuori della funzione che chiama la roba DOP: Inoltre, è possibile gestire da o morire () o possiamo dire come MySQL. ma sarà davvero varia. È possibile nascondere i messaggi di errore pericolose nella produzione girando displayerrors spento e solo leggendo il vostro log degli errori. Ora, dopo aver letto tutte le cose di cui sopra, si sta probabilmente pensando: cosa diavolo è che quando voglio solo iniziare appoggiato semplice SELECT. INSERIRE. AGGIORNARE. o DELETE Non ti preoccupare, qui andiamo: Selezione dei dati Allora, cosa state facendo in MySQL è: Ora nel PDO. si può fare questo come: Nota. Se si utilizza il metodo come di seguito (query ()), questo metodo restituisce un oggetto PDOStatement. Quindi, se si vuole recuperare il risultato, utilizzarlo come sopra. In PDO dati, si ottiene tramite l'-gtfetch (). un metodo del gestore di istruzioni. Prima di chiamare recuperare, l'approccio migliore sarebbe dicendo DOP come youd come i dati siano scaricati. Nella sezione sottostante sto spiegando questo. Fetch Modalità Si noti l'uso della DOP :: FETCHASSOC nel codice fetch () e fetchAll () di cui sopra. Questo dice PDO per restituire le righe come un array associativo con i nomi dei campi come chiavi. Ci sono molti altri modi di prendere troppo che vi spiegherò uno per uno. Prima di tutto, mi spiego come per selezionare la modalità recuperare: In quanto sopra, ho utilizzato fetch (). È inoltre possibile utilizzare: PDOStatement :: fetchAll () - Restituisce un array contenente tutti i risultati di righe che figurano PDOStatement :: fetchColumn () - restituisce una singola colonna della riga successiva di un set di risultati PDOStatement :: fetchObject () - Estrae la riga successiva e restituisce come un oggetto. PDOStatement :: setFetchMode () - Impostare la modalità predefinita recuperare per questa affermazione Ora vengo a prendere modalità: PDO :: FETCHASSOC. restituisce un array indicizzato in base al nome della colonna come restituito nel set di risultati DOP :: FETCHBOTH (default): restituisce un array indicizzato da entrambi nome della colonna e 0-indicizzato numero di colonna come restituito nel set di risultati ci sono ancora più scelte leggere su di loro tutto in PDOStatement Fetch documentazione. . Ottenere il conteggio delle righe: Invece di usare mysqlnumrows per ottenere il numero di righe restituite, è possibile ottenere un PDOStatement e fare rowCount (). come: Ottenere l'ultimo inserito ID di inserimento e aggiornamento o DELETE quello che stiamo facendo in funzione mysql è: E in DOP, la stessa cosa può essere fatto: Nel sopra interrogazione PDO :: exec esegue un'istruzione SQL e restituisce il numero di affetti righe. Inserire e cancellare verranno spiegate successivamente. Il metodo di cui sopra è utile solo quando non si utilizza variabile nella query. Ma quando è necessario utilizzare una variabile in una query, non mai mai provato come il sopra e là per dichiarazione preparata o dichiarazione con parametri è. Prepared statement D. Qual è una dichiarazione preparata e perché ho bisogno di loro A. Una dichiarazione preparata è una dichiarazione pre-compilato SQL che può essere eseguito più volte inviando solo i dati al server. Il flusso di lavoro tipico di utilizzo di una dichiarazione preparata è la seguente (citato da Wikipedia tre 3 punti): preparare. Il modello economico è creato dall'applicazione e inviato al sistema di gestione di database (DBMS). Alcuni valori sono lasciati non specificato, chiamati parametri, segnaposto o si legano variabili (etichettati sotto.): INSERT INTO PRODUCT (nome, prezzo) VALORI Il DBMS analizza, compila ed esegue l'ottimizzazione delle query sul modello dichiarazione, e memorizza il risultato (.) senza eseguirlo. Eseguire . In un secondo momento, le forniture di applicazione (o lega) i valori per i parametri, e il DBMS esegue l'istruzione (possibilmente restituzione di un risultato). L'applicazione può eseguire l'istruzione quante volte si vuole con valori diversi. In questo esempio, potrebbe fornire pane per il primo parametro e 1,00 per il secondo parametro. È possibile utilizzare una dichiarazione preparata includendo segnaposto nel vostro SQL. Ci sono fondamentalmente tre quelli senza segnaposti (Non provare questo con la variabile suo sopra di uno), uno con segnaposto senza nome, e uno con i segnaposto di nome. D. Quindi ora, che cosa sono chiamati segnaposti e come li uso A. nome segnaposto. Utilizzare nomi descrittivi preceduti dai due punti, invece di punti interrogativi. Noi non si preoccupano positionorder di valore in nome segnaposto: È inoltre possibile associare utilizzando un eseguire array come pure: Un'altra caratteristica piacevole per gli amici OOP è che segnaposto di nome hanno la possibilità di inserire gli oggetti direttamente nel database, assumendo le proprietà corrisponde al nome campi. Per esempio: D. Ora, quali sono i segnaposto senza nome e come li uso A. Diamo un esempio: In quanto sopra, si può vedere quelli. invece di un nome come in un titolare del nome di luogo. Ora, nel primo esempio, assegniamo variabili ai diversi segnaposto (stmt-gtbindValue (1, nome, DOP :: ParamStr)). Poi, assegniamo dei valori a tali segnaposto ed eseguire l'istruzione. Nel secondo esempio, il primo elemento dell'array va al primo. e la seconda alla seconda. NOTA . In segnaposto senza nome dobbiamo prenderci cura del corretto ordine degli elementi nella matrice che stiamo passando alla PDOStatement :: metodo Execute (). SELEZIONARE. INSERIRE. AGGIORNARE. DELETE query preparate Amine, No, non lo è. Mentre NullPoite davvero fatto un ottimo lavoro di scrittura, questo è certamente isn39t una buona lettura, perché è così lungo. I39m abbastanza sicuro, che l'8 di 10 visitatori semplicemente ignorarlo. E hai anche una spiegazione, perché questo top isn39t risposta votato. Una parte TLDR in principio sarebbe una buona idea, credo. ndash trejder 4 luglio 14 alle 11:00 In primo luogo, permette di iniziare con il commento standard che diamo tutti: Per favore, dont funzioni usare MySQL in nuovo codice. Non sono più mantenute e sono ufficialmente deprecati. Vedere la scatola rossa. Ulteriori informazioni su istruzioni preparate, invece, e utilizzare DOP o MySQLi - questo articolo vi aiuterà a decidere quale. Se si sceglie DOP, ecco un buon tutorial. Consente di passare attraverso questo, frase per frase, e spiegano: Non sono più mantenuti, e sono ufficialmente deprecati Questo significa che la comunità PHP viene gradualmente abbandonare il supporto per queste molto vecchie funzioni. E 'probabile che non esiste in una versione futura (recente) di PHP L'uso continuato di queste funzioni possono rompere il vostro codice nel (non così) lontano futuro. Newer extmysql è stata rimossa in PHP 7 Invece, si dovrebbe imparare di istruzioni preparate - estensione mysql non supporta le istruzioni preparate. che è (tra le altre cose) una contromisura molto efficace contro SQL Injection. E 'fissata una gravissima vulnerabilità in applicazioni dipendenti MySQL, che consente agli aggressori di ottenere l'accesso allo script e di eseguire ogni possibile domanda sul database. Quando si va in qualsiasi pagina di manuale funzione mysql, si vede una scatola rossa, spiegando che non deve più essere utilizzato. Utilizzare DOP o MySQLi Ci sono migliori, più robusti e ben costruiti alternative, DOP - PHP oggetto di database. che offre un approccio completo OOP all'interazione database e MySQLi. che è un miglioramento specifico MySQL. Facilità di utilizzo Le ragioni analitiche e sintetiche sono stati già accennato. Per i nuovi arrivati ​​theres un incentivo più significativo di smettere di usare le funzioni di MySQL datati. API di database contemporanei sono solo più facile da usare. I suoi lo più i parametri legati che possono semplificare il codice. E con ottimi tutorial (come visto sopra) il passaggio alla DOP è neanche eccessivamente arduo. Riscrittura una base di codice più grande al tempo stesso però richiede tempo. DTRE Raison per questo intermedio alternativa: funzioni DOP equivalenti al posto di MySQL utilizzando gt lt pdomysql. php è possibile passare dalle vecchie funzioni di MySQL con il minimo sforzo. Si aggiunge DOP involucri di funzioni che sostituiscono le loro controparti di MySQL. Semplicemente includeonce (pdomysql. php) in ogni script invocazione che deve interagire con il database. Rimuovere il prefisso funzione mysql ovunque e sostituirlo con DOP. mysql connect () diventa DOP connect () query MySQL () diventa DOP query () numRows mysql () diventa numRows DOP () mysql insertid () diventa DOP insertid () mysql fetcharray () diventa DOP fetcharray () mysql fetchassoc () diventa pdo fetchassoc () mysql realescapestring () diventa DOP realescapestring () e così via. Il tuo codice funziona allo stesso modo e ancora in gran parte lo stesso aspetto: voil Et. Il tuo codice sta usando DOP. Ora è il momento di utilizzare in realtà. parametri legati possono essere facile da usare Hai solo bisogno di una API meno ingombrante. pdoquery () aggiunge il supporto molto facile per i parametri legati. Conversione vecchio codice è semplice: spostare le variabili fuori dalla stringa SQL. Aggiungi loro come separati da virgole parametri della funzione di pdoquery (). Mettere punti interrogativi. come segnaposto dove le variabili sono stati prima. Sbarazzarsi di singole citazioni che in precedenza racchiusi valuesvariables stringa. Il vantaggio diventa più evidente per il codice più lunghe. Spesso le variabili stringa arent solo interpolate in SQL, ma concatenati con fuga chiamate in mezzo. Con. segnaposto applicate non dovete perdere tempo con che: Ricordate che DOP consente ancora uno o. Basta non sfuggire a una variabile e associarlo nella stessa query. La funzionalità segnaposto è fornito dalla vera PDO dietro. Così anche permesso: liste segnaposto nome in seguito. Ancora più importante è possibile passare le variabili RICHIESTA sicuro dietro ogni query. Quando i campi ltformgt presentate corrispondono alla struttura del database esattamente la sua ancora più breve: tanta semplicità. Ma torniamo a un po 'di riscrittura consiglia e motivi tecnici su cui si consiglia di sbarazzarsi di mysql e fuggire. Fissare o rimuovere le funzionalità disinfettare oldschool () Dopo aver convertito tutte le chiamate a mysql pdoquery con params rilegati, rimuovere tutte le chiamate pdorealescapestring ridondanti. In particolare si dovrebbe correggere eventuali disinfettare o funzioni puliti o filterThis o cleandata come pubblicizzato tutorial datati in una forma o l'altra: più eclatante errore qui è la mancanza di documentazione. Più significativamente l'ordine del filtro è esattamente nell'ordine sbagliato. ordine corretto sarebbe stato: stripslashes deprecatedly come la chiamata più interno, quindi la disposizione. striptags dopo. htmlentities per contesto di output, e solo infine il escapestring la sua applicazione deve precedere direttamente il intersparsing SQL. Ma, come primo passo solo sbarazzarsi della chiamata realescapestring. Potrebbe essere necessario mantenere il resto della vostra funzione disinfettare () per ora se il database e il flusso di applicazione si aspettano le stringhe HTML-contesto-safe. Aggiungi un commento che essa si applica solo HTML fuga d'ora in poi. gestione StringValue è delegata a DOP e delle sue dichiarazioni parametri. Se ci fosse alcuna menzione di stripslashes () nella funzione di disinfettare, si può indicare una svista livello superiore. E 'stato comunemente lì per annullare i danni (doppio escape) dalle magicquotes obsoleti. Che però è meglio fissato centralmente. Non stringa stringa. Utilizzare uno degli approcci di inversione userland. Quindi rimuovere le stripslashes () nella funzione di disinfettare. nota storica sul magicquotes. Tale caratteristica è giustamente deprecato. Il suo spesso erroneamente descritti come caratteristica di sicurezza fallito però. Ma magicquotes sono tanto una caratteristica di sicurezza fallito come palle da tennis hanno fallito come fonte di nutrimento. Che semplicemente wasnt il loro scopo. L'implementazione originale in PHP2FI introdotto esplicitamente con solo citazioni verrà automaticamente fuggiti rendendo più facile per passare i dati dei moduli direttamente di msql query. In particolare è stato accidentalmente sicuro da usare con mSQL. come quello supportato solo ASCII. Poi PHP3Zend reintrodotto magicquotes per MySQL e misdocumented esso. Ma in origine era solo una caratteristica di praticità. Non intendo per la sicurezza. Come disposto dichiarazioni differiscono Quando rimescolate le variabili stringa nella query SQL, si pretende molto semplicemente ottenere più complicato per voi da seguire. Il suo sforzo anche estranei per MySQL di segregare codice e dati di nuovo. iniezioni SQL semplicemente sono quando i dati sanguina nel contesto del codice. Un server di database sopraelevazione dopo punto in cui PHP originariamente incollata variabili trascorre clausole di query. Con parametri associati a separare il codice SQL e SQL valori al contesto nel codice PHP. Ma non ottiene mischiato di nuovo dietro le quinte (tranne che con PDO :: EMULATEPREPARES). Il database riceve i comandi SQL invariate e 1: 1 i valori delle variabili. Anche se questa risposta sottolinea che si dovrebbe preoccuparsi circa i vantaggi di leggibilità di cadere mysql. Theres di tanto in tanto anche un vantaggio prestazionale (inserti ripetuto con valori solo diversi) a causa di questa separazione datacode visibile e tecnico. Attenzione che il legame ancora parametro è neanche una soluzione one-stop magia contro tutte le iniezioni SQL. Gestisce l'uso più comune per datavalues. Ma il cant whitelist identificatori tabella nome della colonna, aiutare con la costruzione clausola dinamica, o liste valori di matrice semplicemente. Hybrid DOP utilizzare queste funzioni DOP involucro fanno un tappabuchi API di codifica da usare. (La sua più o meno quello MySQLi avrebbe potuto essere se non fosse stato per l'idiosincratica spostamento firma della funzione). Si espongono anche il vero DOP al più volte. Riscrittura Non deve fermarsi a utilizzando i nuovi nomi delle funzioni DOP. Si potrebbe ad uno ad uno ogni transizione pdoquery () in una pianura PDO-preparare () - execute () chiamata. La sua migliore per iniziare a semplificare di nuovo però. Ad esempio, il recupero risultato comune: può essere sostituito con solo una iterazione foreach: O meglio ancora un diretto e completo recupero matrice: Youll ottenere più utile avvertenze nella maggior parte dei casi di DOP o MySQL di solito forniscono query dopo falliti. Altre opzioni per cui questo si spera visualizzate alcune ragioni pratiche e un percorso worthwile a cadere mysql. Proprio il passaggio a DOP doesnt tutto tagliato. pdoquery () è anche solo un frontend su di esso. A meno che non si introduce anche il parametro vincolante o può utilizzare qualcos'altro dal API più bello, è un interruttore inutile. Spero che la sua ritratti abbastanza semplice da non favorire l'abbattimento ai nuovi arrivati. (Istruzione di solito funziona meglio di divieto.) Mentre si qualifica per la più semplice-cosa-che-potrebbe-possibilmente-lavoro categoria, la sua anche ancora molto codice sperimentale. Ho appena scritto che durante il fine settimana. C'è una pletora di alternative però. Solo Google per PHP di astrazione del database e navigare un po '. Ci sono sempre stati e saranno un sacco di ottime librerie per tali compiti. Se si vuole semplificare ulteriormente l'interazione del database, mapper come ParisIdiorm sono la pena di provare. Proprio come nessuno usa il DOM blando in JavaScript più, non dovete fare da babysitter un'interfaccia database di grezzo al giorno d'oggi. risposto 24 dicembre 13 alle 23:30 Parlando di ragioni tecniche, ci sono solo pochi, estremamente preciso e raramente utilizzato. Molto probabilmente non si sarà mai mai usarli nella vostra vita. Può essere Sono troppo ignorante, ma non ho mai avuto l'opportunità di usare loro le cose come non bloccante, asincrono query stored procedure che ritornano più gruppi di risultati di crittografia (SSL) Compression Se bisogno di loro - questi sono senza dubbio ragioni tecniche di allontanarsi da MySQL estensione verso qualcosa di più elegante e dall'aspetto moderno. Tuttavia, ci sono anche alcune questioni non tecniche, che possono rendere la vostra esperienza un po 'più difficile l'ulteriore utilizzo di queste funzioni con le versioni di PHP moderni aumenteranno le comunicazioni a livello deprecato. Essi semplicemente possono essere disattivati. in un futuro lontano da poter essere eventualmente rimossi dalla generazione predefinito PHP. Non è un grosso problema anche, come ext mydsql verrà spostato in PECL e ogni hoster sarà felice di complie PHP con esso, dato che non vogliono perdere clienti i cui siti sono stati di lavoro per decenni. forte resistenza da parte della comunità StackOverflow. molto tempo si parla di queste funzioni onesti, è stato detto che sono sotto stretto tabù. essendo un utente medio php, molto probabilmente la vostra idea di utilizzare queste funzioni è soggetto a errori e sbagliato. Proprio a causa di tutti questi numerosi tutorial e manuali che insegnano modo sbagliato. Non le funzioni stesse - devo sottolineare - ma il modo in cui vengono utilizzati. Quest'ultimo problema è un problema. Ma, a mio parere, la soluzione proposta non è migliore neanche. Mi sembra troppo idealista un sogno che tutti gli utenti di PHP impareranno a gestire le query SQL correttamente in una sola volta. Molto probabilmente avrebbero solo cambiare mysql per MySQLi meccanico, lasciando l'approccio stesso. Soprattutto perché mysqli rende l'uso istruzioni preparate incredibile doloroso e fastidioso. Senza contare che le istruzioni preparate nativi arent abbastanza per proteggere dalle iniezioni SQL, e né mysqli né DOP offre una soluzione. Così, invece di combattere questa estensione onesto, Id preferiscono combattere le pratiche sbagliate ed educare le persone nel modo giusto. Inoltre, ci sono alcuni falsi o non significative ragioni, come pretende di supporto Stored Procedure (che stavamo usando mysqlquery (CALL myproc) per le età) Operazioni di supporto incaricato di tirare (come sopra) pretende di supporto più istruzioni (che ne hanno bisogno) non in fase di sviluppo attivo (così che cosa si influisce in alcun modo pratico) Manca una interfaccia OO (per creare uno è una questione di parecchie ore) di supporto Doesnt prepared statement o parametrizzate interroga un quest'ultima è un punto interessante. Anche se ext mysql non supportano istruzioni preparate nativi, arent necessari per la sicurezza. Possiamo istruzioni preparate facilmente falsi utilizzando segnaposto gestite manualmente (proprio come DOP fa): voilà. tutto è parametrizzato e sicuro. Ma va bene, se non gradite la casella rossa nel manuale, un problema di scelta si pone: mysqli o DOP Bene, la risposta sarebbe la seguente: Se si capisce la necessità di usare un livello di astrazione del database. e alla ricerca di una API per creare uno, mysqli è una scelta molto buona, in quanto supporta in effetti molte caratteristiche specifiche di MySQL. Se, come eri maggior parte delle persone PHP, si utilizza API prime chiamate nel codice dell'applicazione (che è essenzialmente pratica sbagliata) - DOP è l'unica scelta. come questa estensione finge di essere non solo API, ma piuttosto un semi-DAL, ancora incompleto, ma offre molte caratteristiche importanti, con due di loro fa DOP criticamente distingue da mysqli: a differenza di mysqli, PDO può legare segnaposto per valore. il che rende le query costruite dinamicamente fattibili senza più schermate di codice piuttosto confusa. a differenza di mysqli, PDO può sempre tornare risultato della query in un semplice array di consueto, mentre mysqli può farlo solo su installazioni mysqlnd. Quindi, se sei un utente medio PHP e si vuole risparmiare un sacco di mal di testa quando si usano le istruzioni preparate nativi, DOP - ancora una volta - è l'unica scelta. Tuttavia, PDO non è un proiettile d'argento troppo, e ha le sue difficoltà. Così, ho scritto soluzioni per tutti i problemi comuni e casi complessi nel tag wiki DOP Tuttavia, tutti a parlare di estensioni mancanti sempre i 2 fatti importanti circa MySQLi e DOP: preparati dichiarazione è neanche un proiettile d'argento. Ci sono identificatori dinamici, che non può essere vincolata usando istruzioni preparate. Ci sono domande dinamici con numero imprecisato di parametri che fa richiesta la costruzione di un compito difficile. Né funzioni mysqli né DOP devono essere apparso nel codice dell'applicazione. Ci dovrebbe essere un livello di astrazione tra di loro e il codice di applicazione, che farà tutto il lavoro sporco del legame, looping, la gestione degli errori, ecc all'interno, rendendo il codice dell'applicazione asciutto e pulito. Soprattutto per i casi complessi come la costruzione di query dinamica. Quindi, solo il passaggio a DOP o mysqli non è sufficiente. Uno deve usare un ORM, o di un generatore di query, o qualsiasi database di classe astrazione invece di chiamare le funzioni API prime nel loro codice. E invece - se si dispone di un livello di astrazione tra il codice dell'applicazione e MySQL API - si pretende molto in realtà importa quale motore viene utilizzato. È possibile utilizzare mysql ext fino a quando non va deprecato e quindi facilmente riscrivere la classe di astrazione ad un altro motore, avendo tutto il codice dell'applicazione intatto. Ecco alcuni esempi basati sulla mia classe safemysql per mostrare come una tale classe di astrazione dovrebbe essere: confronta questa una linea singola con quantità di codice è necessario DOP. Quindi confrontare con quantità folle di codice è necessario con MySQLi prime istruzioni preparate. Si noti che la gestione degli errori, profilatura, la registrazione di query già costruito e funzionante. Confronto con soliti inserti DOP, quando ogni singolo nome del campo viene ripetuto sei a dieci volte - in tutti questi numerosi denominate segnaposto, attacchi e le definizioni di query. Difficilmente si può trovare un esempio per i prodotti DOP gestire tale caso pratico. E sarà troppo verboso e molto probabilmente non sicuri. Così, ancora una volta - non è solo conducente grezzo dovrebbe essere la vostra preoccupazione, ma di classe di astrazione, utile non solo per gli esempi sciocchi da manuale principianti ma per risolvere qualsiasi problemi della vita reale. Come non è in fase di sviluppo attivo solo per questo fatto-up 390,0139 Se si costruisce qualcosa con questa funzione stand-still, aggiornare il vostro mysql-versione in un anno e finire con un sistema non funzionante, I39m sicuro che ci sono un sacco di la gente improvvisamente in quel 390.0139. I39d dicono che deprecato e non in fase di sviluppo attivo sono strettamente correlati. Si può dire che non vi è quotno reasonquot degna per questo, ma il fatto è che quando le viene offerta una scelta tra le opzioni, nessuno sviluppo attivo è quasi altrettanto male come deprecato I39d dire ndash Nanne 1 Feb 13 in 10:21 ShaquinTrifonoff: certo, si doesn39t utilizzare istruzioni preparate. Ma nessuno dei due fa DOP. che la maggior parte delle persone consigliamo sopra MySQLi. Quindi I39m non sono sicuro che ha un impatto significativo qui. Il codice di cui sopra (con un po 'più di analisi) è ciò che fa DOP quando si prepara una dichiarazione di default. ndash ircmaxell 4 Febbraio 13 alle 12:44 Questa risposta è scritta per mostrare quanto banale è quello di bypassare il codice utente-convalida PHP scritto male, come (e con che cosa) questi attacchi funzionano e come sostituire le vecchie funzioni di MySQL con un sicuro dichiarazione preparata - e in fondo, perché gli utenti StackOverflow (probabilmente con un sacco di rep) abbaiano a nuovi utenti fanno domande per migliorare il loro codice. Prima di tutto, non esitate a creare questa banca dati di test mysql (che ho chiamato il mio prep): Con il fatto che, possiamo passare al nostro codice PHP. Consente di assumere il seguente script è il processo di verifica per un amministratore su un sito web (semplificato ma di funzionare se si copia e usarlo per il test): sembra abbastanza legit a prima vista. L'utente deve inserire una login e password, proprio brillante, non entrate nella seguente: L'uscita è la seguente: Super lavoro come previsto, consente ora di cercare il nome utente e la password attuale: Amazing Hi-Five tutto, il codice correttamente verificato un amministratore. La sua perfetta Beh, non proprio. Diciamo che l'utente è un po 'persona intelligente. Diciamo che la persona sono io. Inserire il seguente: e l'uscita è: Congratulazioni, hai appena mi ha permesso di inserire il tuo amministratori di super-protetto solo sezione con me entrare in un falso nome utente e una password falsa. Scherzi a parte, se non mi creda, creare il database con il codice che ho fornito, ed eseguire questo codice PHP - che a colpo d'occhio sembra davvero di verificare il nome utente e la password piuttosto bene. Quindi, in risposta, è per questo che vengono sgridato. Quindi, consente di dare un'occhiata a cosa è andato storto, e perché ho appena ricevuto sul suo super-admin-solo-bat-caverna. Ho preso una supposizione e pensato che werent facendo attenzione con i tuoi ingressi e semplicemente li passai al database direttamente. Ho costruito l'ingresso in un tht modo cambierebbe la query che sono stati realmente in esecuzione. Allora, che cosa è stato che dovrebbe essere, e che cosa ha finiscono per essere Ecco la query, ma quando abbiamo sostituire le variabili con gli ingressi reali che abbiamo usato, si ottiene il seguente: Guarda come ho costruito la mia password in modo che fosse prima chiudere l'apice singolo giro la password, poi introdurre un nuovo confronto poi, proprio per la sicurezza, ho aggiunto un'altra stringa in modo che il singolo citazione otterrebbe chiuso come previsto nel codice inizialmente abbiamo avuto. Tuttavia, questo non è circa la gente che urla a voi ora, si tratta di che vi mostra come rendere il codice più sicuro. Okay, allora cosa è andato storto e come possiamo risolvere il problema Questo è un attacco SQL injection classico. Uno dei più semplici per quella materia. Sulla scala di vettori di attacco, si tratta di un bambino di attaccare un carro armato - e vincente. Quindi, come possiamo proteggere la vostra sezione amministrativa sacro e rendere piacevole e fissare la prima cosa da fare sarà quello di smettere di usare quelle funzioni veramente vecchi e obsoleti MySQL. Lo so, hai seguito un tutorial che hai trovato on-line e funziona, ma il suo vecchio, il suo obsoleto e nel giro di pochi minuti, ho appena rotto passato senza nemmeno una goccia di sudore. Ora, si hanno le migliori possibilità di utilizzare mysqli o DOP. Personalmente sono un grande fan di DOP, quindi userò DOP nel resto di questa risposta. Ci sono pro e contro, ma personalmente trovo che i pro superano di gran lunga i contro. Il suo portatile su più motori di database - se si sta utilizzando MySQL o Oracle o un po 'cruento nulla - semplicemente cambiando la stringa di connessione, ha tutte le caratteristiche di fantasia che vogliamo usare, ed è bello e pulito. Mi piace pulito. Ora, consente di avere uno sguardo a quel codice, questa volta scritta utilizzando un oggetto PDO: Le differenze principali sono che non ci sono più funzioni mysql. E 'tutto fatto tramite un oggetto PDO, in secondo luogo, che usa una dichiarazione preparata. Ora, che cosa è una dichiarazione prepred si chiede E 'un modo per dire il database prima di eseguire una query, ciò che la query è che stiamo andando a correre. In questo caso, diciamo il database: Ciao, ho intenzione di eseguire un'istruzione select che vogliono id, userid e passare da parte degli utenti della tabella in cui l'ID utente è una variabile e il pass è anche una variabile .. Poi, nella dichiarazione esecuzione , si passa il database un array con tutte le variabili che ora si aspetta. I risultati sono fantastici. Consente di cercare quelli nome utente e combinazioni di password da prima volta: non era utente verificato. Eccezionale. Oh, ho appena ricevuto un po 'emozionato, ha funzionato: Il controllo passa. We have a verified admin Now, lets try the data that a clever chap would enter to try to get past our little verification system: This time, we get the following: This is why you are being yelled at when posting questions - its because people can see that your code can be bypassed wihout even trying. Please, do use this question and answer to improve your code, to make it more secure and to use functions that are current. Lastly, this isnt to say that this is PERFECT code. There are many more things that you could do to improve it, use hashed passwords for example, ensure that when you store sensetive information in the database, you dont store it in plain text, have multiple levels of verification - but really, if you just change your old injection prone code to this, you will be WELL along the way to writing good code - and the fact that you have gotten this far and are still reading gives me a sense of hope that you will not only implement this type of code when writing your websites and applications, but that you might go out and research those other things I just mentioned - and more. Write the best code you can, not the most basic code that barely functions. answered Sep 18 13 at 12:28 Because (amongst other reasons) its much harder to ensure the input data is sanitized. If you use parametrized queries, as one does with PDO or mysqli you can entirely avoid the risk. As an example, some-one could use enhzflep) drop table users as a user name. The old functions will allow executing of multiple statements per query, so something like that nasty bugger can delete a whole table. If one were to use PDO of mysqli, the user-name would end-up being enhzflep) drop table users The old functions will allow executing of multiple statements per query - no, they won39t. That kind of injection is not possible with extmysql - the only way this kind of injection is possible with PHP and MySQL is when using MySQLi and the mysqlimultiquery() function. The kind injection that is possible with extmysql and unescaped strings is things like 39 OR 39139 391 to extract data from the database that was not meant to be accessible. In certain situations it is possible to inject sub queries, however it is still not possible to modify the database in this way. ndash DaveRandom Dec 30 12 at 20:58 The MySQL extension is the oldest of the three and was the original way that developers used to communicate with MySQL. This extension is now being deprecated in favor of the other two alternatives because of improvements made in newer releases of both PHP and MySQL. MySQLi is the improved extension for working with MySQL databases. It takes advantage of features that are available in newer versions of the MySQL server, exposes both a function-oriented and an object-oriented interface to the developer and a does few other nifty things. PDO offers an API that consolidates most of the functionality that was previously spread across the major database access extensions, i. e. MySQL, PostgreSQL, SQLite, MSSQL, etc. The interface exposes high-level objects for the programmer to work with database connections, queries and result sets, and low-level drivers perform communication and resource handling with the database server. A lot of discussion and work is going into PDO and its considered the appropriate method of working with databases in modern, professional code. answered Sep 2 15 at 7:20 I find the above answers really lengthy, so to summarize: The mysqli extension has a number of benefits, the key enhancements over the mysql extension being: Object-oriented interface Support for Prepared Statements Support for Multiple Statements Support for Transactions Enhanced debugging capabilities Embedded server support As explained in the above answeres, the alternatives of mysql are mysqli and pdo. API supports server-side Prepared Statements. Supported by MYSQLi and PDO API supports client-side Prepared Statements. Supported only by PDO API supports Stored Procedures. Both MySQLi and PDO API supports Multiple Statements and all MySQL 4.1 functionality - Supported by MySQLi and mostly also by PDO Both MySQLi and PDO where introduced in PHP5.0, whereas MySQL was introduced prior to PHP3.0. A point to note is MySQL is included in PHP5.x though deprecated in later versions. A full-text index in MySQL is an index of type FULLTEXT. Full-text indexes can be used only with InnoDB or MyISAM tables, and can be created only for CHAR. VARCHAR. or TEXT columns. As of MySQL 5.7.6, MySQL provides a built-in full-text ngram parser that supports Chinese, Japanese, and Korean (CJK), and an installable MeCab full-text parser plugin for Japanese. Parsing differences are outlined in Section 13.9.8, ngram Full-Text Parser. and Section 13.9.9, MeCab Full-Text Parser Plugin. A FULLTEXT index definition can be given in the CREATE TABLE statement when a table is created, or added later using ALTER TABLE or CREATE INDEX. For large data sets, it is much faster to load your data into a table that has no FULLTEXT index and then create the index after that, than to load data into a table that has an existing FULLTEXT index. Full-text searching is performed using MATCH(). AGAINST syntax. MATCH() takes a comma-separated list that names the columns to be searched. AGAINST takes a string to search for, and an optional modifier that indicates what type of search to perform. The search string must be a string value that is constant during query evaluation. This rules out, for example, a table column because that can differ for each row. There are three types of full-text searches: A natural language search interprets the search string as a phrase in natural human language (a phrase in free text). There are no special operators. The stopword list applies. For more information about stopword lists, see Section 13.9.4, Full-Text Stopwords. Full-text searches are natural language searches if the IN NATURAL LANGUAGE MODE modifier is given or if no modifier is given. For more information, see Section 13.9.1, Natural Language Full-Text Searches. A boolean search interprets the search string using the rules of a special query language. The string contains the words to search for. It can also contain operators that specify requirements such that a word must be present or absent in matching rows, or that it should be weighted higher or lower than usual. Certain common words (stopwords) are omitted from the search index and do not match if present in the search string. The IN BOOLEAN MODE modifier specifies a boolean search. For more information, see Section 13.9.2, Boolean Full-Text Searches. A query expansion search is a modification of a natural language search. The search string is used to perform a natural language search. Then words from the most relevant rows returned by the search are added to the search string and the search is done again. The query returns the rows from the second search. The IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier specifies a query expansion search. For more information, see Section 13.9.3, Full-Text Searches with Query Expansion. For information about FULLTEXT query performance, see Section 9.3.4, Column Indexes. For more information about InnoDB FULLTEXT indexes, see Section 15.8.10, InnoDB FULLTEXT Indexes. The myisamftdump utility dumps the contents of a MyISAM full-text index. This may be helpful for debugging full-text queries. See Section 5.6.2, myisamftdump Display Full-Text Index information. Posted by Dyfed Lloyd Evans on October 21, 2002 Hyphen 039-039 characters break literals at the moment. A search for something like quotGATA-D22S690quot finds all entries containing GATA and not the full hyphenated text. The 039-039 character is treated as a word stop even within literals. The same is true if any of the special text search modifiers are used (eg found with full text searches. Posted by Patrick O039Lone on December 9, 2002 It should be noted in the documentation that IN BOOLEAN MODE will almost always return a relevance of 1.0. In order to get a relevance that is meaningful, you039ll need to: ltBRgtltBRgt SELECT MATCH(039Content039) AGAINST (039keyword1 keyword2039) as Relevance FROM table WHERE MATCH (039Content039) AGAINST(039keyword1 keyword2039 IN BOOLEAN MODE) HAVING Relevance gt 0.2 ORDER BY Relevance DESC ltBRgtltBRgt Notice that you are doing a regular relevance query to obtain relevance factors combined with a WHERE clause that uses BOOLEAN MODE. The BOOLEAN MODE gives you the subset that fulfills the requirements of the BOOLEAN search, the relevance query fulfills the relevance factor, and the HAVING clause (in this case) ensures that the document is relevant to the search (i. e. documents that score less than 0.2 are considered irrelevant). This also allows you to order by relevance. ltBRgtltBRgt This may or may not be a bug in the way that IN BOOLEAN MODE operates, although the comments I039ve read on the mailing list suggest that IN BOOLEAN MODE039s relevance ranking is not very complicated, thus lending itself poorly for actually providing relevant documents. BTW - I didn039t notice a performance loss for doing this, since it appears MySQL only performs the FULLTEXT search once, even though the two MATCH clauses are different. Use EXPLAIN to prove this. Posted by Nathan Ostgard on April 14, 2003 An easy solution to correct for spelling errors for small search items like the name of the city is to build a column that contains the SOUNDEX of each. I039ve found that using a 4 character SOUNDEX works the best. An example: ALTER TABLE cities ADD citysoundex VARCHAR(4) NOT NULL UPDATE cities SET citysoundexLEFT(SOUNDEX(cityname),4) And then to query against: SELECT FROM citites WHERE citysoundexLEFT(SOUNDEX(039Some City Name039),4) Posted by Jim Nguyen on June 18, 2003 The full-text search is slow when there are a lot of rows in the table. I have more than 2 million rows with text and multiple word searches (3 or more) take about 30 seconds to a minute or longer. I am running a Athlon 2.2 Ghz with 512 MB DDR RAM 400 Mhz. Hard drive has seek time of 9 ms. Posted by Alan Riley on July 14, 2003 We too have a database with close to 6 million rows in it. We would like to use the fulltext search, but it is painfully slow. The sad thing is that any one query we need to run only needs to be run on a subset of the rows (think of those 6 million rows as being divided between about 80 different categories, with results only needed to be returned from within a category). It is a shame that there isn039t some way for us to have a fulltext index within the rows of another column which is also indexed. Our next shot at this is going to be to create 80 different tables, one for each category (yuck), just to try to get decent performance on the within-category fulltext search. I would think there is enough interest in fulltext search for there to be an email list dedicated to it where those of us who need to use it on real-world web sites could interact with the developers to try to tune it for the good of the community at large. Posted by Donal McMullan on September 24, 2003 The nature of fulltext indexing is such that the more 039words039 (of greater than the minimum length) that appear in the columns you index, the greater will be size of the index, and the time it takes to create and search that index. 4 Million rows x 6 words per row 24 Million entries 4 Million rows x 30 words per row 120 Million entries If you index intelligently, you may well find that the feature meets your needs, despite what some users may have remarked above. quotNumber of rowsquot is useless as a benchmarking statistic on its own. Posted by Erlend Strmsvik on October 23, 2003 I039ve got a webshop running with mysql. We have 1.6 million booktitles in our database, and our fulltext index is from title and 039extra039 title. Maybe around 5-7 words on average per record. Any fulltext search in our database takes around 1-5ms. A three word search can take a few seconds but still faster than anything else. Even Amazon. This is from our main server which has several thousand hits every day. We are one of the biggest booksellers in my country. - This was in 039reply039 to someone posting earlier about poor performance in 039real world situation039. Posted by Jerome C on December 3, 2003 We have a vast database of products (totaling 3 million rows). The rebuild of the full-text index took 21 minutes to complete. As for the search, a multiple word search on the full-text index of 1 field is as follows: 20 rows returned Query took 1.0263 sec The size of the index is very big though. Index 449,529 KB We are going to eliminate unnecessary words which should make the index smaller. Posted by Ben Margolin on December 19, 2003 The indexing process definitely depends on your machine config. I indexed the same dataset, same mysql version (4.0.16, - standard on Linux, - nt on XP). First machine: a 512M Athlon 2100 running WinXP on a RAID1 array, and it took 9 mins 20 sec. Second machine: 1G RAM P4-2.0ghz, running Linux 7.3 (2.4.20-13.7 kernel), one-spindle (but fast) IDE disk, and it took 29 mins 11 sec. The query was quotalter table msgbodies add fulltext ftibodies (subject, body)quot, and the dataset is about 550M, 1.3 million rows. Both machines were mostly idle when the indexing occurred. I know it039s just anecdotal, but if you run a big alter as I did, don039t be surprised if it takes a while. oh yeah, and then be prepared for MUCH longer than normal insert times when you add large data to the FT indexed columns. This makes sense of course, but, at least on my dataset and hardware, is positively NOT neglible. FYI. Posted by Jeffrey Yuen on February 2, 2004 Full text searching in 4.1.1 For Chinese charset in UTF-8 encoding. It needed to set ftminwordlen 1 Posted by Eric Jacolin on February 4, 2004 (MySQL 4.1) To make FULLTEXT MATCH work with Japanese UTF-8 text, be careful that words from your Japanese text be separated by the ASCII space character, not Japanese UTF-8 (or other) spacing characters. (when using phpMyAdmin to manage data write a SQL query, you must switch away from your Japanese IME to insert a space char. ) Posted by Tom Cunningham on February 5, 2004 Tom039s fulltext tips: To get MySQL searching well for me I did: 1. Have a normalized versions of the important columns: where you039ve stripped punctuation and converted numerals to words (0391039 to 039one039). Likewise normalise the search string. 2. Have a combined fulltext index on your searchable columns to use in your 039WHERE039 clause, but then have separate fulltext indexes on each column to use in the 039ORDER BY039 clause, so they can have different weights. 3. For the scoring algorithm, include the independent importance of that record, and include a match of the inclusive index against stemmed versions of the search words (as: quotweddingquot gt quotwedquot, quotweddingsquot). 4. If there039s exactly one result, go straight to that record. 5. If you get no results, try matching against the start of the most important column (WHERE column LIKE 039term039), and put a 5-character index on that column. This helps if someone is searching on a very short word or a stopword. 6. Reduce minimum word length to 3, and make a new stopwords list just using quota an and the is in which we you to on this by of withquot. Use quotREPAIR TABLE xxx QUICKquot to rebuild the index and make a note of the index-file (xxx. MYI) size before and after you make changes. Then use ftdump to tune. Posted by Attila Nagy on April 19, 2004 More about performance: Fulltext search in MySQL isn039t slow really. It039s slower than normal index selects, but that039s not noticable. I039m playing tables that each contains ca 4million records, about 6GB of text that needs to be indexed. The problem lies in the optimization of the queries, that use the MATCH() and AGAINST() functions. So far as I found out MySQL can use in a query only one index. The optimizer looks for the index that will possibly give the smallest amount of rows, then goes trough all of these, and removes those records, that fall out because of the other WHERE statements. When you enter a fulltext search, the server has to use that index. Any other statments could be applied only to the rows that were returned by the search. If you have lots of records, most of the searches will return lots of results. The rest of your query will be executed like if you were executing it against a table that contains the results, and no indexes - obviously that will be processed sequentially. Same thing applies when you use the SQLCALCFOUNDROWS, or LIMIT with high offset values: first the server has to load all the results, then the limit could be applied. If you have to use the fulltext, these are some hints how you could get quite good results: - Try to avoid any group, where, order and any statements for what it039s necessary to get all the results. I know, usually this is impossible. - If you need to show the results on a web page, try to find other methods to get the total number of results than using SQLCALCFOUNDROWS. Better if you don039t tell the user at all how many results there are ) - If indexing text that is in other language than english, before doing anything create a stopword file for your language (That could reduce index size about 30) But most important: think a lot, before you decide to use fulltext search Posted by Peter Dunham on April 22, 2004 We are doing fulltext searches of around 200 tables of 14 -12 million rows each. Upgrading a twin cpu 2Ghz linux machine (running ES 3) from 1GB to 3GB RAM and increasing keybuffersize from 384MB to 512MB has seen load averages go from 1.5-2 to around 0.5, with same usage. Posted by Peter Grigor on May 29, 2004 I039m not sure I agree with your comment that Mysql always uses a fulltext index if you include match. against. I tried a sample query where I used match. against and another value in the where clause (on the primary keyed field) and Mysql039s optimizer picked the primary key index. The statement looked like quotselect something from sometable where match(col1, col2) against (039some text here039) and pkcol 44 Posted by JT Johnston on July 1, 2004 dev. mysqldocmysqlenFulltextBoolean. html states you cannot do a full-text search in Boolean Mode by relevancy. You can, but you need mysql version 4. Take note of quotORDER BY relevancy DESCquot. Here is my codeexample: SELECT, MATCH (YR, AU, ST, SD, SC, BT, BD, BC, AT, AD, AC, JR, KW, AUS, GEO, AN, RB, CO, RR) AGAINST (039Margaret Atwood039 IN BOOLEAN MODE) AS relevancy FROM cclmain WHERE MATCH (YR, AU, ST, SD, SC, BT, BD, BC, AT, AD, AC, JR, KW, AUS, GEO, AN, RB, CO, RR) AGAINST (039Margaret Atwood039 IN BOOLEAN MODE) ORDER BY relevancy DESC Posted by James Day on August 19, 2004 See The Full-Text Stuff That We Didn039t Put In The Manual at dev. mysqltech-resourcesarticlesfull-text-revealed. html for more information about full-text search. Posted by James R on August 31, 2004 Thought some benchmarks for a very large data set might be useful to people. I created a full-text index on a 100 gig database, where the index was on a column where the data totals 3 gig. The index added 2 gig to the database. The database has 2,741,000 records. The textual content is technical literature in US English. Machine: The machine is an Athlon XP 3200 w 1 gig RAM, one drive for the OS, and another 250GB EIDE drive for the MySQL data. OS is Redhat 9. Index creation: 3 hours 5 min. Most of that time was probably copying the table (since MySQL copies the table before it modifies it). The process was definitely disk-limited -- CPU usage was never regularly above 50. I believe that were it not for the excess data to copy, the index creation would have taken about 45 minutes. Queries were chosen to compare rare words, common words, and words of different lengths. All queries seemed to be disk-limited (CPU utilization hardly moved off baseline), which makes sense given that there is not enough RAM to hold the index in memory. All queries were done mutiple times and the average time reported. Results follow. Word, Rows, Seconds, SecondsRow ---------------------------------------- bilobed, 4, 0.15, 0.0375 mends, 4, 0.19, 0.0475 nanotechnology, 23, 0.64, 0.0278 bioluminescent, 53, 1.53, 0.0289 photosynthesis, 81, 2.21, 0.0273 graphite, 5070, 123.00, 0.0243 bicycle, 5385, 122.00, 0.0227 titanium, 13503, 350.00, 0.0259 (titanium, graphite), 18423, 425.00, 0.0231 metal, 151095, 4020.00, 0.0266 This is just a small test on the way to indexing the full 100 gig in the database that I am working on for freepatentsonline. I039ll post results for that once I have a new server built. Posted by noel darlow on September 3, 2004 In reply to Patrick O039Lone039s post, above: The first, non-boolean MATCH can039t keep pace with the second, boolean one since it does not recognise the boolean operators. A search for foo might turn up rows with foo, foobar, foofighters, etc but the non-boolean, relevance MATCH can039t quotcountquot anything except foo. Same problem with a phrase search. Since effectively you can039t use boolean operators in the second, boolean MATCH, it039s rendered pointless. Results could be post-processed with your own ranking algorithm but it039s kind of odd that you can039t do a boolean search AND rank results in the query. Posted by Dave M on September 12, 2004 Those looking to simply match a search phrase in a large group of words, try this: SELECT FROM data WHERE haystack LIKE (039needle039) AND haystack RLIKE 039:lt:needle:gt:039 This query will produce the same result as the following query, but is roughly 20X faster. SELECT FROM data WHERE haystack RLIKE 039:lt:needle:gt:039 For more than one word use: haystack LIKE (039word1word2039) AND haystack RLIKE 039:lt:word1:gt:.:lt:word2:gt:039 Posted by James Day on September 26, 2004 The Wikipedia encyclopedia uses MySQL boolean full text search and MySQL 4.0.20. You can assess the speed yourselves. About 350,000 articles rows in the English language version, roughtly 5GB total. For all languages, one million articles and 10GB of text. It039s very important to have a sufficiently large keybuffersize. Get much of the index in RAM and searches are typically very fast. Because we use InnoDB tables and can039t share cache between InnoDB and MyISAM, we039re moving to a setup which will use a dedicated and MyISAM tuned search server. We run a slow query killer which will kill queries once their allowed time expires. That time depends on server load (active thread count). Documented at wp. wikidevQuerybane It turns out that our current search often spends most time on things other than full text search - an improved version which is much more efficient is pending. Remember that you can use a self join to get around the one index per query limit of MySQL. Search remains our most problematic load feature, requiring a couple of quite capable slaves to keep up at busy time. If we039re working on the servers and the remainder can039t handle the load, we switch to Google or Yahoo search. This is from one of the top few hundred sites on the net, so it039s scaling pretty well for our application. One server was sufficiently fast to take us to the top 1,000. Posted by Andrew Panin on October 7, 2004 Hi all I had a problem with FULLTEXT search and after I solved it, I want to try to help you. I thought that FULLTEXT search is slow. That was. But I did a simple trick: 1. For example, we have 4 tables with fulltext index. We need to perform fast search on them. 2. Do the following: CREATE TEMPORARY TABLE xxx SELECT id, name, MATCH(name) AGAINST (039searchstring039) AS relevancy FROM table1 INSERT INTO xxx SELECT id, name, MATCH(name) AGAINST (039searchstring039) AS relevancy FROM table2. 3. Then, when the temporary table is filled with the data, do the simple select from it: SELECT id, name FROM xxx ORDER BY relevancy DESC I think, it is the optimal way to make a VERY FAST fulltext search from a number of tables. I hope, this will be helpful. Posted by Dennis van den Ende on December 27, 2004 Allthough my fulltext serach works fine, i still have problems with it. i compare products with there prices. i used the quotrelevancequot idea (written above). But it will not recognize it correctly. Heres my query: SELECT , MATCH( field ) AGAINST (039blabla039) as relevance FROM table WHERE MATCH( field ) AGAINST (039blabla039 IN BOOLEAN MODE ) HAVING relevance gt 0.2 for example it finds 18 rows. to increase the rows, i checked (manuelly) the relevance. 3 above 18 (all 18.xxx) and the rest about 10.3 or lower. If i increase the quothavingquot to 15, it finds only 2 of 3. The field i use is the only index-field and ofcourse a fulltext specific field. it seems that the relevance is taking part of the search results. i am still looking for another idea but the relevance would cover my needs 100 update I just updated the mysql version from 4.0.15 to 4.1.8 and it works perfectly. Posted by Mauricio Wolff on February 4, 2005 to set up minlen and stopwordfile in windows (win2k or xp): 1. run services. msc to check what. ini your mysql is reading (in my case, quotC:MySQLbinmysqld-ntquot --defaults-filequotC:MySQLmy. iniquot MySQL) 2. change your my. ini like this: mysqld ftminwordlen3 ftstopwordfilequotC:MySQLstop. txtquot 3. restart your mysqld at services. msc 4. reindex your table using REPAIR TABLE tblname QUICK Posted by Peter Laursen on April 28, 2005 it is legal to use two different arguments with the quotdouble match constructionquot, i. e. select . match (artist, album, title) against (039blues in orbit039) from musicfiles where match (artist, album, title) against (039ellington039) will FIND all records with 039ellington039 as substring of artist, album or title, but will RATE them as the search match039es 039blues in orbit039 You can even. ORDER BY or GROUP BY MATCH (kunstner, albumtitel, titel) AGAINST (039prelude to a kiss039). or against anything else Posted by Grant Harrison on June 9, 2005 Maybe a little off topic here. Alternatively, instead of doing all full-text search within MySql database, you can pull data out and create an index on it. It039s a much faster search. I am using DBSight to search on 1.7million records of 1.2G data, on a P3 450MHz, 256MRam, with sub-second performance. Taking search out of database also give you capability to customize stemmer and query parser. Posted by Erik Petersen on July 13, 2005 When using FULLTEXT queries on large set data sets it039s critical to LIMIT your results. Doing some experimentation has made this very clear. Using a data set of 5.5 million rows of forum message posts indexed with a single FULLTEXT index: select id, match(post) against(039foo039) as score from messages where match (body) against( 039foo039 ) . 155323 rows in set (16 min 7.51 sec) select id, match(post) against(039foo039) as score from messages where match (body) against( 039foo039 ) limit 100 . 100 rows in set (1.25 sec) I ran a number of other tests on various terms known to be in the text with similar results. These were run in reverse order shown. Make sure you return only the rows you need or you will suffer. For a search engine application returning pages of results keep in mind that nobody is going to ever see page 74 Cap the results to a reasonable maximum trading response time for completeness where possible. Posted by kim markegard on August 25, 2005 In regards to Dyfed Lloyd Evans comment, I believe that quot. quot will also cause this which is unfortunate because we have product name acronyms we039d like to seach. Posted by Nathan Huebner on October 29, 2005 After tons of hours today working on this, I HAVE FINALLY MASTERED THE TECHNIQUE OF USING THIS THING. This query is what you send to your MySQL to return the results. I put the LIMIT so that you don039t overflow. queryretquotSELECT ProductID, Title, Description, Price, RetailPrice, MATCH (Title) AGAINST (039keyword039) AS score FROM server. book HAVING score gt 0 LIMIT start, maxretquot This query will COUNT the number of rows it found. (I believe that039s correct), I don039t believe it counts occurrences, just rows. I saw that if you pull back without a LIMIT above, and count that way, it039s 100000x slower. So do your count like this: querycountquotSELECT count(MATCH(Title) AGAINST(039keyword039)) AS score FROM server. book WHERE MATCH (Title) AGAINST (039keyword039) HAVING score gt 0quot Make sure you have your Primary Key setup, your Title and Description as SEPARATE FULLTEXT INDEXES. I spent a few hours boggling over this. Posted by Saqib Aziz on November 24, 2005 There is no way to perdict what maximum relevance rank could be. While working with full text searches one may want to show percentages as the criteria for indicating how close a particular record was to the search query. To achieve this, one way is to select the maximum relevance rank or score and then use it( as a denominator ) with every single record score to get percentage equivalent of score. For the sake of example, consider we have 6 as maximum rank and 2,3,4.234 are scores for three different records. Now to get percentage we have to do simple maths i. e. we can divide each score by 6(max rank) and then mulitply the result with 100. Hope this helps someone. Posted by Nathan Huebner on January 12, 2006 Tips on how to maximize performance, and minimize return time. Let me guess: you have a lot of data, and you went ahead and FULLTEXT indexed a column within that large pile of data. To put it in simple words: not cool. How long does your data take to return from a FULLTEXT search. 5 seconds More If you039re returning data under 3 seconds, then you039re ok, but if you want it to return in 1.3 seconds, here039s what I did. 1. Dont fulltext index a column within a huge table. Instead, take a Unique Identifier, and the text you039re searching, and copy it to another table. Use this to export your columns: SELECT uniquecolumn, mytextsearchcolumn FROM mydatabase. mytable INTO OUTFILE quotc:pathoutfile. txtquot That will export your data to a file in Tab Delimited format. Now, create a new table somewhere, and call it fulltextengine or something, with only 2 columns (less is better), you could add one more if you need to. Now import your data: LOAD DATA INFILE quotc:pathoutfile. txtquot IGNORE INTO TABLE mydatabase. fulltextengine Now, create your FULLTEXT index on your search field. Grande. Now you have a separate table for searching. So if you want to try it out, go into MySQL, and try this, or PHPmyAdmin: SELECT SQLCALCFOUNDROWS uniquecolumn, searchcolumn, MATCH (searchcolumn) AGAINST (039Keyword Goes Here039) AS score FROM mydatabase. fulltextengine HAVING score gt 0 Hope this helps It may add extra maintenance, but I will give up my soul to increase search speeds by 6x. Posted by Joe Soap on July 11, 2006 Not sure if this is useful for people trying to reduce their search dataset. But what I039m doing is preprocessing the text before I add it to the database. So I add the full text to my FileData column, but I also preprocess the text and put this processed text into a Keywords column. Then I search only the keywords column and never the full text. This technique obviously (you039ll see why) doesn039t work for phrase matching but it may speed up the search time by reducing the size of the dataset to search. Here039s the algorithm I use. 1. extract the text 2. count each word of 2 or more characters in the text and record the frequency that each occurs 3. from this list of words 2 or more characters long, remove the k (k currently 500) most common words in the english dictionary 4. sort the list so that the most frequently occurring words appear first 5. take the first n words as the final keywords, where n gt 0 and n lt the total number of remaining words Posted by Tasuku SUENAGA on July 30, 2006 If you have performance problems on fulltext search, Please try Senna, fulltext search engine that can be embedded in MySQL. qwik. jpsenna Original MySQL fulltext search is slow for query SELECT COUNT() or SELECT FROM xx LIMIT largenumber, x. These queries are very fast with Senna039s 2ind patch. Posted by Gary Osborne on August 19, 2006 I039m not convinced that stop-words are of great value. Sure, they might reduce the size of the index and speed-up queries for some kinds of databases. But there are two fundamental flaws with quotmandatoryquot stop-words. Firstly, without knowing in advance the nature of the data, how can any programmer proclaim to know which words should be excluded because they have no value Secondly, if a user includes any stop word in a search query, then by definition that word039s value can not be zero. If the word039s value was zero, then why would the user use it in a search query If you need to disable stop-words without re-compiling, consider appending a character to the end of each word in your text before inserting your text into the database. I used quotqquot. I also right-padded all words shorter than 4 characters to a length of 4 characters by appending quotqquots. And I appended a quot quot to the end of my text string before inserting into the database. After retrieving my text from the database, I did a global replace on my text. I changed quotqqqquot to quotquot, quotqqquot to quotquot, and quotq quot to quot quot - in that order - to restore the text to it039s original form. That was not the best solution but it worked. Luckily for me, my text was simply a space delimited list of words without and punctuation. Otherwise, my quotqquot encoding and decoding would have been more difficult. Posted by Sebastian Alberoni on September 27, 2006 Combining MATCH with MAX, GROUP BY and ORDER BY can be of a lot of help when retrieving results in the correct order regarding relevance. For example, using this I could solve a problem with one table called 039Professional039, which had a many-to-many reference to another table 039Profession039. Although I was using DISTINCT I was getting duplicate results because of different relevance values that MATCH was giving to the different entrances in 039Professions039. Here I am copying the final query that worked OK (it039s a bit simplified): select distinct p. idProfessional, MAX(MATCH (pssion. name, pssion. description) AGAINST (039string to search039)) as professionRanking FROM professional p, professionalprofession pp, profession pssion WHERE pp. ProfessionalidProfessional p. idProfessional AND pp. ProfessionidProfession pssion. idProfession and ( MATCH (pssion. name, pssion. description) AGAINST (039string to search039) GROUP BY p. idProfessional ORDER BY professionRanking DESC Posted by Miguel Velilla meucat on May 20, 2007 The truth behind fulltext search, is that MySql first split text into single words, then indexes isolated words pointing to records. These are logical steps that many of us previously had tried before MySql fulltext commands creation. I created a PHP program some years ago to perform exactly the same split-and-index task. This is the reason MATCH command allows prefixed wildcards but not postfixed wilcards. Since single words are indexed, a postfix wildcard is impossible to manage in the usual way index does. You can039t retrieve 039nited states039 instantly from index because left characters are the most important part of index. Even so, I hope MySql developers some day implement postfix wildcars, because for many of us, it is important to perform a truly 039full text039 search. To say something, if I have a record with the word 039database039. I want retrieve this record when searching by 039tabas039, an impossible task for actual fulltext search command. It039s easy to see that such a command can gain lot of performance, even when MySql developers be obliged to search byte to byte into the indexed words. If you have a big table with text descriptions. to say 1 GB size, it is possible that quantity of different words into text will not pass from 500.000, maybe 1.000.000 words, averaging 8 bytes each, total 8 MB of data to be browsed, instead the 1 GB you should seek byte to byte to find what you want. This is a 1 GB 8 MB 125. or two orders of magnitude lower in terms of processing. Posted by Sergejzr Zr on July 27, 2007 Unfortunately it is not possible to combine Fulltext field and normal (i. e integer) field into one index. Since only one index per query can be used, that seems be a problem Table: id(integer primary key)content(text fulltext indexed)status(integer key) Note that executing folowing query, mysql will use only one index. Either fulltext, or status (Depending on intern statistics). Q1: SELECT FROM table WHERE MATCH(content) AGAINST(039searchQuery039) AND status 1 However it is still possible to use both indexes in one query. You will need a new index on id, status pair and use join. Thus mysql will be able to use one index for each table. Q2: SELECT t1. from table t1 LEFT JOIN table t2 ON(t1.idt2.id) WHERE MATCH(t1.content)AGAINST(039searchQuery039) AND status1 Q2 will run significantly faster than Q1 at least in my case :) Note the overhead: You will need an id for each row and a key wich is spanned over needed fields strating with id. Posted by Phoebe Bright on August 14, 2007 Using this for the first time I picked an unfortunate test and took a while before I worked out why it wasn039t working. In the hopes of saving other newbies some time: This will work: SELECT FROM myfile WHERE description LIKE 039sea039 But this will return nothing: SELECT FROM myfile WHERE MATCH (description) AGAINST (039sea039) BECAUSE THE DEFAULT MIN LENGTH IS 4 need to set ftminwordlen to 3 in the configuration file if you want it to work. Posted by Mohamed Mahir on September 28, 2007 To get the first exact matching record of the Full text search i wrote like this.. SELECT MATCH (column) AGAINST (039keyword039) relevancy FROM t1 WHERE MATCH (column) AGAINST (039keyword039) ORDER BY relevancy DESC LIMIT 1 Posted by Neil Delargy on October 19, 2007 One solution to find a word with a dashes or hyphens in is to use FULL TEXT SEARCH IN BOOLEAN MODE, and to enclose the word with the hyphen dash in double quotes. Posted by Derek Foreman on October 31, 2007 I use Mediawiki that makes use of the FullText searching and was not getting results I knew were in the database. After reading this page I realized that mysql won039t index words 3 characters or less by default. The solution is detailed clearly in this page Change the ftminwordlen setting. You can find what the server is using by running: SHOW VARIABLES LIKE 039ft039 Then you039ll have to rebuild the indexes on the tables that have FULLTEXT indices, because the server I039m using had several databases I needed a quick way to identify which tables these were. SELECT DISTINCT TABLESCHEMA, TABLENAME FROM COLUMNS WERE COLUMNKEY 039MUL039 I could then rebuild the tables. Posted by Jane Doe on November 28, 2007 Very fast and flexible, and works nice with MySQL. Eliminates many of the issues mentioned here in the comments, also ) MATCHAGAINST didn039t work how I intended. Here039s how I finally solved what I thought MATCHAGAINST should have been doing from the beginning: Posted by Carlos Dias on August 8, 2011 Basically this approach makes me think twice because of the next logical steps: 1- If your working in one table with a lot of records. each time the records are updated or new lines inserted the index must be (obviously)recreated. if it039s myisam. writing operations the table is locked. 2- I guess that the best approach towards this it039s probably the logic of: when tables are huge. not creating indexes for text search. create cachesql. (cachesql is one index). Somehow anticipating these problems. like i write are not problems to ignore. Why this is the best option. because if people use one file to log the last writing operations and compare it with the file that contains the results cache(best approach. cronjob). it039s only necessary to point to the file that contains the resultscache. The logic of:If there are 500 000 000 of conjugations of wordsphrases, etc what039s the need of indexing everything if only 50 000 conjugations are usedseeked, etc. Posted by Bradley Smith on February 21, 2012 Alan, instead of creating 80 different tables, one for each category, why not partition the table by the category so the records with that category would be grouped together within the partition and then your only searching within the specific category and more direct and faster route to the data you want to search Posted by Nasser W on September 2, 2013 MySQL fulltext search works well for Arabic. Just make sure of the following where needed: 1. COLLATION utf8unicodeci amp CHARACTER SET utf8. (Databases, Tables, and Columns). 2. Index words of 3 letters and more. This is Very Important for Arabic, ftminwordlen 3 (see show variables like quotftquot) 3. Check the version of MySQL (5.5 or 5.6), and Engine (InnoDb or MyIsam) Sign Up Login You must be logged in to post a comment. Using MySQL Stored Procedures with PHP mysqlmysqlipdo Wondering how to use stored procedures with PHP and MySQL So was I and here8217s what I8217ve learned. In this tutorial I8217ll explain how to use PHP (I8217m using 5.2.6) to call MySQL (I8217m using 5.0.2) stored procedures using the following database extensions: First we need to setup our enviroment which consists of a new database with one table and two stored procedures. In your db tool of choice (I8217ll be using the MySQL Query Browser ) create a new database named test . After you create the new database, make sure to add a user called example with password example to the database and give it read access. CREATE DATABASE test Now create the table users : DROP TABLE IF EXISTS test. users CREATE TABLE test. users 40 usersid INT 40 10 41 UNSIGNED NOT NULL AUTOINCREMENT , firstname VARCHAR 40 100 41 NOT NULL , lastname VARCHAR 40 100 41 NOT NULL , PRIMARY KEY 40 usersid 41 41 ENGINE INNODB DEFAULT CHARSET latin1 Before we create the stored procedures, lets put some dummy data in the users table. To do that just run the following query: INSERT INTO test. users VALUES 40 NULL. 8216Joey8217. 8216Rivera8217 41. 40 NULL. 8216John8217. 8216Doe8217 41 Next create the first stored procedure getuser : DELIMITER DROP PROCEDURE IF EXISTS test. getuser CREATE PROCEDURE test. getuser 40 IN userId INT , OUT firstName VARCHAR 40 100 41 , OUT lastName VARCHAR 40 100 41 41 BEGIN SELECT firstname, lastname INTO firstName, lastName FROM users WHERE usersid userId END DELIMITER Finally create the second and last stored procedure getusers : DELIMITER DROP PROCEDURE IF EXISTS test. getusers CREATE PROCEDURE test. getusers 40 41 BEGIN SELECT FROM users END DELIMITER If you understand the sql above, skip this section. The first script we ran to create a database is pretty self explanitory. The second script will delete the table users if it8217s already in your database then it will recreate it. The table will consist of three fields: usersid . firstname . and lastname . The insert script will create two users: 8216Joey Rivera8217 and 8216John Doe8217. If stored procedures are new to you, don8217t worry. They aren8217t that complicated once you start playing with them. When looking at the code for the first stored procedure, drop procedure works the same way as dropping a table. First you want to check if the stored procedure is there and deleted before you recreate it. Create does just that, create the stored procedure in the database. getuser has three parameters: userId . firstName . and lastName . IN means when this stored procedure is called, this variable should be passed with a value. OUT means after the stored procedure executes, it will set the OUT variables with a value that can then be retrieved. You can also have INOUT variables but we don8217t need them for this example. The blulk of the code for the stored procedure goes in the BEGIN to END block. getuser is selecting the first and last name fields from the table users where the user id is equal to the userId variable being passed in. The other thing happening here is the two OUT variables are getting the values retrieved from the select statement. Variable firstName is set to the field firstname and lastName is being set to lastname . That8217s it for getuser . getusers doesn8217t have any IN nor OUT variables. When that stored procedure is executed it will return a recordset instead of variables. Now that we have our environment set, we are ready to start our tests. Depending on what you are trying to achieve, you may be using mysql . mysqli . or PDO . I8217m going to run the same tests with all three to show you the difference as well as the limitation of mysql compared to mysqli and PDO . One of the tests I8217ll be running doesn8217t work with mysql while all the tests work with mysqli and PDO . The three tests will be: A simple select statement Calling stored procedure passing IN variable and retrieve OUT variables 8211 getuser Calling stored procedure with no parameters and returns a recordset 8211 getusers Below is the code to run all three tests with each of the database extensions: print 8216lth3gtMYSQL: calling sp returning a recordset 8211 doesn 8217 t worklth3gt8217 rs mysqlquery 40 8216CALL getusers()8217 41 while 40 row mysqlfetchassoc 40 rs 41 41 123 debug 40 row 41 125 MYSQLI mysqli new mysqli 40 8216localhost8217. 8216example8217. 8216example8217. 8216test8217 41 print 8216lth3gtMYSQLI: simple selectlth3gt8217 rs mysqli - gt query 40 8216SELECT FROM users8217 41 while 40 row rs - gt fetchobject 40 41 41 123 debug 40 row 41 125 print 8216lth3gtMYSQLI: calling sp with out variableslth3gt8217 rs mysqli - gt query 40 8216CALL getuser(1, first, last)8217 41 rs mysqli - gt query 40 8216SELECT first, last8217 41 while 40 row rs - gt fetchobject 40 41 41 123 debug 40 row 41 125 print 8216lth3gtMYSQLI: calling sp returning a recordsetlth3gt8217 rs mysqli - gt query 40 8216CALL getusers()8217 41 while 40 row rs - gt fetchobject 40 41 41 123 debug 40 row 41 125 PDO pdo new PDO 40 8216mysql:dbnametesthost127.0.0.18217. 8216example8217. 8216example8217 41 print 8216lth3gtPDO: simple selectlth3gt8217 foreach 40 pdo - gt query 40 8216SELECT FROM users8217 41 as row 41 123 debug 40 row 41 125 print 8216lth3gtPDO: calling sp with out variableslth3gt8217 pdo - gt query 40 8216CALL getuser(1, first, last)8217 41 foreach 40 pdo - gt query 40 8216SELECT first, last8217 41 as row 41 123 debug 40 row 41 125 print 8216lth3gtPDO: calling sp returning a recordsetlth3gt8217 foreach 40 pdo - gt query 40 8216CALL getusers()8217 41 as row 41 123 debug 40 row 41 125 When you run this code you get the following results: MYSQL. calling sp returning a recordset 8211 doesn 8216t work Warning: mysqlfetchassoc(): supplied argument is not a valid MySQL result resource in test. php on line 24 MYSQLI: simple select stdClass Object ( usersid gt 1 firstname gt Joey lastname gt Rivera ) stdClass Object ( usersid gt 2 firstname gt John lastname gt Doe ) MYSQLI: calling sp with out variables stdClass Object ( first gt Joey last gt Rivera ) MYSQLI: calling sp returning a recordset stdClass Object ( usersid gt 1 firstname gt Joey lastname gt Rivera ) stdClass Object ( usersid gt 2 firstname gt John lastname gt Doe ) PDO: simple select Array ( usersid gt 1 0 gt 1 firstname gt Joey 1 gt Joey lastname gt Rivera 2 gt Rivera ) Array ( usersid gt 2 0 gt 2 firstname gt John 1 gt John lastname gt Doe 2 gt Doe ) PDO: calling sp with out variables Array ( first gt Joey 0 gt Joey last gt Rivera 1 gt Rivera ) PDO: calling sp returning a recordset Array ( usersid gt 1 0 gt 1 firstname gt Joey 1 gt Joey lastname gt Rivera 2 gt Rivera ) Array ( usersid gt 2 0 gt 2 firstname gt John 1 gt John lastname gt Doe 2 gt Doe ) As you can see from the results above, mysql could not get the recordset returned by the stored procedure while mysqli and PDO could. After some more research, some people mentioned (Bob8217s World. php ) that by adding 8216false,655368217 to the end of the mysqlconnect line, mysql could then get recordsets from stored procedures. I tried this and in fact it does work. So by changing mysql mysqlconnect 40 8216localhost8217. 8216example8217. 8216example8217 41 mysql mysqlconnect 40 8216localhost8217. 8216example8217. 8216example8217. false. 65536 41 all the different database extensions work on all tests. So in the end, it seems all of these can work with stored procedures just as well. I hope this was helpful and feel free to leave any questions or comments. EDIT: I have made a new post about doing the above but with a stored procedure that has inout params as well as returns a recordset. Post at: Using MySQL stored procedures with inout and returns a recordset Personally I don8217t use stored procedures to reduce load time, I do it to organize my application better (as well as other reasons). I like having the db take care of itself and have the least amount of queries in my code. It almost makes it feel like the db can function as a standalone 8216app8217 with any code you want to build around it. To answer your question though, I do care about load time and I8217m always working on optimizing code or queries to get the fastest execution times. For my projects I always use caching. Once the stored procedure is optimized and runs great 8211 you can use explain to check your queries (dev. mysqldocrefman5.0enexplain. html ), my code will cache the results returned by the stored procedure so I don8217t have to keep calling it unnecessarily. If the data changes, then I clear the cache file and query the sp again. I also 8211 in my development environment, print out all the queries I run per page, how long each query took, and how long each page took to execute. Here8217s an example of the data I post for me to analyze and make sure things are running fast: connect CALL spuserselectview(10000, id, msg) SELECT id, msg CALL spbiouserselect(10000, 1, id, msg) SELECT id, msg Executed 5 queries in 0.0021560192108154 seconds Average query length: 0.00043120384216309 seconds Queries per second: 2319.0887979653 Longest query length: 0.00091314315795898 Longest query: connect page load time: 0.092291116714478 (tracks how long the page took to completely execute) As you can tell, the stored procedures are running extremely quick, they don8217t slow down the load times at all. Connecting to the db was the slowest part. In reality my biggest load is the Zend Framework itself which is no issue to me since it offers so much and it8217s not too bad of a hit anyways. I use a method in the ZF to display this information but you can get it from the basic mysql class in php as well. The page load time is simply a starttime before anything gets called and then an endtime when the page is done and I show the difference. Your second question is whether to do more heavy lifting in code or in the database. This probably depends on the application but for things I8217ve done, I know I will be using caching so I know I won8217t be hitting the database as much and put a bit more work in the database end by using the stored procedures. I tend to run a couple extra queries in my stored procedures to validate data and error check instead of relying on the data coming from the code. I validate in code as well, but I want my database to work as a standalone and not rely on an outside source. With mysql extension You will be unable to execute stored procedure returning record set twice or more. As a result of second call to mysqlquery you will get Error: 8220Commands out of sync you can8217t run this command now8221. This because of calling to stored procedures treated as multi result set query and you need to tell mysql to give you next result. Solution is using mysqli extension, and mysqli functions or object methods: 8211 mysqlimultiquery 8211 mysqliuseresult 8211 mysqlistoreresult 8211 mysqlimoreresults 8211 mysqlinextresult. After each call to stored procedure and getting result set, you need to call mysqlinextresult and check if there more results with mysqlimoreresults. Somethink like this: print MYSQLI: calling sp returning a recordset rs mysqli-gtquery( CALL getusers() ) while(row rs-gtfetchobject()) debug(row) mysqli-gtnextresult() while (mysqli-gtmoreresults()) mysqli-gtnextresult() print MYSQLI: calling sp returning a recordset rs mysqli-gtquery( CALL getusers() ) while(row rs-gtfetchobject()) debug(row) mysqli-gtnextresult() while (mysqli-gtmoreresults()) mysqli-gtnextresult() You also can get multiple recordsets from one stored procedure, if you want, i suppose. 41 by AntKlim on October 29, 2009 - 9:15 am Hello Joey, Thanks for your tutorials. I hope you can help me with my problem. I have a stored procedure: delimiter drop procedure if exists pgetinfo2 create procedure pgetinfo2 () begin declare mheadid int declare mhdname char(50) declare mhdstat char(1) declare mnorows boolean declare mnmrows int default 0 declare ckbhead cursor for select headid, hdname, hdstat from kbhead where headid lt 10 declare continue handler for not found set mnorows true open ckbhead select foundrows() into mnmrows theloop: loop fetch ckbhead into mheadid, mhdname, mhdstat if mnorows then close ckbhead leave theloop end if set mhdname : concat(mhdname, 8216test8217) select mheadid, mhdname, mhdstat end loop theloop When I call this procedure from mysql command line I receive all rows from cursor. But when I call this procedure from PHP-script I receive only one row (the first row from cursor). This is my PHP-script: conn mysqlconnect(8216localhost8217, 8216xxxx8217, 8216xxxx8217, false, 65536) rs mysqlquery(8220call pgetinfo2()8221) while (row (mysqlfetchassoc(rs))) printr(row) echo 82208221 How I can receive all rows from stored procedure Maybe I do some mistakes In advance thanks. Post scriptum Excuse for my English Thank you for your blog, your site has been the only one that has provided me with any success whatsoever. I8217ve modified your example code to fit my own needs and for some reason, I8217m still unable to have my OUT variables to return. I8217m at a loss as my procedure is as simple as they come. My test case and example has been driving me crazy therefore I figured it may be time for me to reach out for some assistance. DROP PROCEDURE IF EXISTS UpgradeAvailable ( IN Platform VARCHAR(45), IN Version VARCHAR(20), OUT VersionID INT(10), OUT DownloadURL VARCHAR(250)) BEGIN SELECT PingletVersionID, VersionDownloadURL INTO VersionID, DownloadURL FROM VersionTable PV WHERE PV. Platform Platform AND PV. Version Version I8217ve thrown together a form to pass various values into the procedure call: A modification to your PHP page to display the results of your Stored Procedure Call: MYSQL mysql mysqlconnect(8216host8217, 8216user8217, 8216pass8217),false,65536 add this to fix issue with recordsets mysqlselectdb(8216database8217, mysql) print 8216MYSQL: simple select8217 rs mysqlquery( 8216SELECT FROM VersionTable8217 ) while(row mysqlfetchassoc(rs)) debug(row) print 8216Print Post Variables8217 print 8216Platform IN 8216 debug(POSTPlatform) print 8216Version IN 8216 debug(POSTVersion) print 8216MYSQL: calling sp with out variables8217 rs mysqlquery( 8216CALL UpgradeAvailable(POSTPlatform, POSTVersion, VersionID, DownloadURL)8217 ) rs mysqlquery( 8216SELECT VersionID, DownloadURL8217 ) while(row mysqlfetchassoc(rs)) debug(row) You can access this temporary page demonstrating the above pages that I have published by accessing the pinglet. mobiusage. dataspform. html with the following parameters: Platform: 8216Joeys Example8217 Version: 82161.08217 Please let me know if you have any questions and thanks again for your willingness to help others.

Comments

Popular Posts