Yii INSERT ... SUR la duplication de mise à JOUR
Je suis en train de travailler sur un Yii projet. Comment puis-je utiliser la DOUBLE fonctionnalité de base de données MySQL ( http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html ) lorsque l'on fait un save() sur un Yii modèle?
Mon MySQL est comme suit:
CREATE TABLE `ck_space_calendar_cache` (
`space_id` int(11) NOT NULL,
`day` date NOT NULL,
`available` tinyint(1) unsigned NOT NULL DEFAULT '0',
`price` decimal(12,2) DEFAULT NULL,
`offer` varchar(45) DEFAULT NULL,
`presale_date` date DEFAULT NULL,
`presale_price` decimal(12,2) DEFAULT NULL,
`value_x` int(11) DEFAULT NULL,
`value_y` int(11) DEFAULT NULL,
PRIMARY KEY (`space_id`,`day`),
KEY `space` (`space_id`),
CONSTRAINT `space` FOREIGN KEY (`space_id`) REFERENCES `ck_space` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Mon PHP est le suivant:
$cache = new SpaceCalendarCache();
$cache->attributes = $day; //Some array with attributes
$cache->save();
Si il y a un doublon dans ma clé primaire (sapce_id,jour), je n'en veux pas à me plaindre, j'ai juste envie de la mettre à jour avec les données les plus récentes.
Je sais comment le faire en SQL brut, je me demandais juste si il y a un propre Yii façon de le faire.
- Ce lien peut être utile... yiiframework.com/doc/guide/1.1/en/database.ar
Vous devez vous connecter pour publier un commentaire.
Vous êtes à l'aide de modèles dans Yii, il est assez simple .. vous essayez de charger un modèle où l'on soupçonne d'avoir des entrées en double, si vous trouvez l'entrée du modèle est chargé d'autre null est de retour. maintenant, si votre modèle est nul tout simplement créer un nouveau modèle. le repos est normal de votre code à insérer un nouvel enregistrement.
Se référer à des postes de contrôleurs de mise à jour de la méthode dans l'exemple d'application Yii blog. J'ai peut-être mal avec l'orthographe des noms de fonction, désolé pour ça.
findByPk()
. Le but de la question était de mettre à jour une ligne si elle existe déjà ou insérez-en une nouvelle. Et alors que l'aide de modèles, c'est comment il va. Bien sûr, ses performances, mais si vous ne voulez pas remplacer Yii c'est la meilleure option disponible. S'il vous plaît venez avec aucune autre alternative, qui sera vraiment utile. Merci les gars...De me répéter deux points principaux à partir des réponses précédentes, je pense que vous devriez garder:
Il y a un autre point, tout en sachant que la concurrence. Bien que de faible trafic des applications de la probabilité, que vous obtiendrez en difficulté est minime (encore jamais zéro), je pense que nous avons toujours être prudent à ce sujet.
À partir d'un point de vue transactionnel,
"INSERT .. ON DUPLICATE UPDATE"
n'est pas équivalente à la sélection dans la mémoire de votre application et de l'insertion ou de mise à jour. La première est une transaction unique, puis la deuxième ne l'est pas.Voici un mauvais scénario:
Dans ce cas, vous allez obtenir une exception (si vous travaillez avec une clé unique, comme vous le faites ici) ou d'une double entrée. Les entrées en double sont beaucoup plus difficile à ramasser (généralement rien de bizarre jusqu'à ce que vos utilisateurs voient des enregistrements en double).
La solution ici est de définir un niveau d'isolement strict, par exemple "serializable", puis d'entamer une transaction.
Voici un exemple pour yii:
Vous pouvez en savoir plus sur les niveaux d'isolation au moins dans les liens suivants et voir ce que chaque niveau d'isolation de a à offrir à l'intégrité des données en échange de la simultanéité
http://technet.microsoft.com/en-us/library/ms173763.aspx
http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
J'ai remplacé beforeValidate() où j'ai vérifié si un doublon. Si l'on n', j'ai mis
$this->setIsNewRecord(false);
Semble fonctionner. Vous ne savez pas comment performant il est.
Le "Double de la Clé de mise à Jour" est spécifique à MySQL langage SQL. Son peu de chances d'être mis en œuvre dans toute couche d'abstraction de données. ZendDB et de les Propulser n'ont pas d'équivalent.
Vous pouvez simuler le comportement par une tentative d'insérer dans un try/catch et de mise à jour si l'insertion échoue avec le bon code d'erreur. (erreur de clé en double).
Je suis d'accord avec @txyoji de l'analyse du problème, mais je voudrais utiliser une solution différente.
Vous pouvez étendre la
save()
méthode du modèle pour rechercher un enregistrement existant, et de le mettre à jour, ou insérer une nouvelle ligne s'il ne le fait pas.vous devez utiliser try catch comme ça: