Données binaires dans MySQL [fermé]

189

Comment stocker des données binaires dans MySQL ?

Geoff Dalgas
la source
2
@Nevir: Quelles informations recherchez-vous précisément? Que pensez-vous qu'il manque aux réponses de @ phpguy et de @ Mat ?
eggyal
Puisque je ne peux pas poster de réponse, je suppose que je vais le faire ici. Si vous souhaitez stocker certaines données binaires, vous pouvez créer une table, configurer un fichier PHP ou un script pour le stocker, et écrire certaines données binaires dans votre table et laisser le script faire son travail. Sérieusement, je ne sais pas vraiment comment utiliser PHP dans d'autres langues ...

Réponses:

139

La réponse de phpguy est correcte mais je pense qu'il y a beaucoup de confusion dans les détails supplémentaires.

La réponse de base est dans un BLOBdomaine de type / attribut de données. BLOB est l'abréviation de Binary Large Object et ce type de données de colonne est spécifique à la gestion des données binaires.

Consultez la page de manuel appropriée pour MySQL .

Tapis
la source
57

Pour une table comme celle-ci:

CREATE TABLE binary_data (
    id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    description CHAR(50),
    bin_data LONGBLOB,
    filename CHAR(50),
    filesize CHAR(50),
    filetype CHAR(50)
);

Voici un exemple PHP:

<?php
    // store.php3 - by Florian Dittmer <[email protected]>
    // Example php script to demonstrate the storing of binary files into
    // an sql database. More information can be found at http://www.phpbuilder.com/
?>

<html>
    <head><title>Store binary data into SQL Database</title></head>

    <body>
        <?php
            // Code that will be executed if the form has been submitted:

            if ($submit) {
                // Connect to the database (you may have to adjust
                // the hostname, username or password).

                mysql_connect("localhost", "root", "password");
                mysql_select_db("binary_data");

                $data = mysql_real_escape_string(fread(fopen($form_data, "r"), filesize($form_data)));

                $result = mysql_query("INSERT INTO binary_data (description, bin_data, filename, filesize, filetype) ".
                                    "VALUES ('$form_description', '$data', '$form_data_name', '$form_data_size', '$form_data_type')");

                $id= mysql_insert_id();
                print "<p>This file has the following Database ID: <b>$id</b>";

                mysql_close();
            } else {

                // else show the form to submit new data:
        ?>
        <form method="post" action="<?php echo $PHP_SELF; ?>" enctype="multipart/form-data">
            File Description:<br>
            <input type="text" name="form_description"  size="40">
            <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
            <br>File to upload/store in database:<br>
            <input type="file" name="form_data"  size="40">
            <p><input type="submit" name="submit" value="submit">
        </form>

        <?php
            }
        ?>
    </body>
</html>
Mauris
la source
9
Ce code ressemble à PHP3 (ou peut-être 4), que register_globals a activé. Vous ne voulez pas exécuter ce code, et il ne fonctionnera pas non plus sur une installation PHP semi à jour (qui est la version 5).
Jusqu'au
27
-1 pour ajoutelashes () où mysql_real_escape_string () est nécessaire. Pouvons-nous arrêter de donner du code aux gens avec des vulnérabilités d'injection SQL? (Non, addlashes () n'est PAS assez bon.)
chaos
40

Je recommande fortement contre le stockage des données binaires dans une base de données relationnelle. Les bases de données relationnelles sont conçues pour fonctionner avec des données de taille fixe; c'est là que réside leur force de performance: rappelez-vous l'ancien article de Joel sur les raisons pour lesquelles les bases de données sont si rapides? car il faut exactement 1 incrément de pointeur pour passer d'un enregistrement à un autre. Si vous ajoutez des données BLOB de taille indéfinie et très variable, vous allez bousiller les performances.

Au lieu de cela, stockez les fichiers dans le système de fichiers et stockez les noms de fichiers dans votre base de données.

Alex Weinstein
la source
11
Je n'ai pas voté contre, mais c'est peut-être dû à lui en laissant entendre que vous ne devriez JAMAIS le faire, plutôt que de dire que c'est une mauvaise idée la plupart du temps. Je suis d'accord avec lui en général, mais pas dans 100% des cas. Il peut y avoir des considérations autres que les performances. Par exemple, je travaille maintenant sur quelque chose où la performance n'a pas du tout d'importance. D'autres facteurs tels que la centralisation, la simplicité et les sauvegardes signifient que dans ce cas, le stockage dans la base de données a du sens. Une autre raison courante est la réplication.
LaVache
4
D'un autre côté, le stockage des données dans db est indépendant du système d'exploitation, ce qui peut être bien pour les noms de fichiers étranges. db peut stocker plusieurs fichiers avec le même nom de fichier, le système d'exploitation ne le peut pas. Il n'a aucun problème de lecture / écriture / suppression. Il n'a pas besoin d'un système de sauvegarde supplémentaire. Et ce n'est pas public. Alors parfois, le développement est rapide. Btw. personne ne vous oblige à tout stocker dans la même base de données, à la fin tout se termine sur un disque.
Joeri
7
@AlexWeinstein, Vous confondez des données binaires avec des données de largeur fixe. Les données binaires peuvent également avoir une largeur fixe. Et les données à largeur fixe ne conviennent pas à toutes les situations. En effet, dans de nombreuses situations, vous bénéficierez de données à largeur variable: lisez le dernier paragraphe de dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Pacerier
4
D'accord avec @Pacerier sur ce point, BINARY (16) est stocké fixe. Comme pour BLOB: Un BLOB a un pointeur de largeur fixe vers les données stockées en dehors de la table. Cela est différent de varchar ou varbinary qui le stockent en ligne. La recherche d'un objet blob nécessite des étapes supplémentaires, mais laissez-le en dehors de votre clause WHERE et c'est très bien.
Garr Godfrey
4
Je pense aussi que le stockage des fichiers dans le système de fichiers est très cassé et non portable. et si le fichier est supprimé?
Garr Godfrey
22

Bien que vous n'ayez pas dit ce que vous stockez, et que vous avez peut-être une bonne raison de le faire, la réponse est souvent «en tant que référence au système de fichiers» et les données réelles se trouvent quelque part sur le système de fichiers.

http://www.onlamp.com/pub/a/onlamp/2002/07/11/MySQLtips.html

Issac Kelly
la source
17

Cela dépend des données que vous souhaitez stocker. L'exemple ci-dessus utilise le LONGBLOBtype de données, mais vous devez savoir qu'il existe d'autres types de données binaires:

TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB
VARBINARY
BINARY

Chacun a ses cas d'utilisation. S'il s'agit d'une longueur connue (courte) (par exemple des données compactées), BINARYou VARBINARYfonctionnera la plupart du temps. Ils ont l'avantage supplémentaire de pouvoir les indexer.

d0nut
la source
14

Bien que cela ne soit pas nécessaire, vous pouvez essayer d' base64encoder les données et de les décoder. Cela signifie que la base de données n'aura que des caractères ascii. Cela prendra un peu plus d'espace et de temps, mais tout problème lié aux données binaires sera éliminé.

utilisateur10117
la source
11

Si le champ BLOB - non recommandé - existe, vous pouvez enregistrer les données de cette façon:

mysql_query("UPDATE table SET field=X'".bin2hex($bin_data)."' WHERE id=$id");

Idée tirée d' ici .

Communauté
la source
10

La question se pose également de savoir comment obtenir les données dans le BLOB. Vous pouvez mettre les données dans une instruction INSERT, comme le montre l'exemple PHP (bien que vous deviez utiliser mysql_real_escape_string au lieu des addlashes). Si le fichier existe sur le serveur de base de données, vous pouvez également utiliser LOAD_FILE de MySQL

Scott Noyes
la source
Ce lien dit que MySQL_real_escape_string est obsolète.
Poul Bak