Using CakePHP 1.3 I would like to save a 0 value for a field if nothing is written in the form field.
Best way is to do it in just MySQL but no success. I have tryed to set:
Null=no and Default = 0; or Null=yes and Default = 0;
Also both combinations combined with CakePHP Behavior which sets in beforeSave or beforeValidate:
$model->data[$name][$field] = 0;
or
unset($model->data[$name][$field]);
also with:
Null=yes and Default = 0; or Null=yes and Default = NULL;
Always the query is :
INSERT INTO `table` (`zero_field`, `other_fields`) VALUES (NULL, 'other_data')
or
INSERT INTO `table` (`zero_field`, `other_fields`) VALUES ('', 'other_data')
And if Null=no getting an error: Column 'zero_field' cannot be null
Even if I unset the field I get the query with the field inside.
How should I save a 0 value in the databese if in the form it is not set or empty?
The zero_field is int(11)
Set null = no, default = 0 for your field in database
Clear model cache files in app/tmp/cache/models/*
Be sure to use Model->create() before saving a new record so that it populates the new record to be saved with default values.
Save and Win.
Related
I am trying to fetch customer id from ":ao.mos:pro:%" and update corresponding doc ":pd:pro:%", we have thousands of ":ao.mos:pro:%" docs and corresponding ":pd:pro:%" for each mo:pro doc.
I am using below query and it works but it updates only one doc it can find indexes.
MERGE INTO `bucket1` AS d
USING `bucket1` AS p
ON d.icc = p.icc AND META(d).id LIKE ':pd:pro:%' AND META(p).id LIKE ':ao.mos:pro:%'
WHEN MATCHED THEN
UPDATE SET d.customerId = p.customerId;
Any suggestions on how to get this working for all matching docs in the bucket.
The following works.
CREATE INDEX ix11 ON `default` (icc, customerId) WHERE META().id LIKE ":ao.mos:pro:%";
CREATE INDEX ix12 ON `default` (icc, customerId) WHERE META().id LIKE ":pd:pro:%";
INSERT INTO default VALUES(":ao.mos:pro:1", {"icc":1, "customerId":100});
INSERT INTO default VALUES(":ao.mos:pro:2", {"icc":2, "customerId":101});
INSERT INTO default VALUES(":pd:pro:1", {"icc":1});
INSERT INTO default VALUES(":pd:pro:2", {"icc":1});
INSERT INTO default VALUES(":pd:pro:3", {"icc":2});
MERGE INTO `default` AS m
USING (SELECT p1.icc, p1.customerId
FROM `default` AS p1
WHERE META(p1).id LIKE ':ao.mos:pro:%' AND p1.icc IS NOT NULL) AS p
ON m.icc = p.icc AND META(m).id LIKE ':pd:pro:%'
WHEN MATCHED THEN
UPDATE SET m.customerId = p.customerId;
MERGE INTO `default` AS m
USING default AS p
ON m.icc = p.icc AND META(m).id LIKE ':pd:pro:%' AND META(p).id LIKE ':ao.mos:pro:%'
WHEN MATCHED THEN
UPDATE SET m.customerId = p.customerId;
Are you having following issue:
First source row matches 2 target rows. Second source matches same target row (by changing icc value to 1 of document key ":ao.mos:pro:2") then returns error (5320 Multiple UPDATE/DELETE of the same document (document key 'xxx') in a MERGE statement) (as with partial updated rows, You need transactions don't want update anything) as you can't update same row again. To resolve that you need to change your ON clause.
If it is a one off operation you can use Eventing Service and create a function with a bucket alias of "src_bkt" to map to bucket1 in r+w mode and the deployment feed boundary set to "From Everything" can easily do 100's of millions of items quickly without indexes.
function OnUpdate(doc,meta) {
// Filter out all non-interesting items
if (!meta.id.startsWith(":pd:pro:")) return;
// No need to do anything already updated.
if (doc.customerId)return;
var myint = meta.id.substring(8);
var otherkey = ":ao.mos:pro:" + myint;
var otherdoc = src_bkt[otherkey];
if (otherdoc) {
if (doc.icc === otherdoc.icc ) {
// update the field as we have a match and it is missing.
doc.customerId = otherdoc.customerId;
src_bkt[meta.id] = doc;
}
}
}
So now you just insert some test documents using the QWB
INSERT INTO bucket1 VALUES(":ao.mos:pro:1", {"icc":1, "customerId":100});
INSERT INTO bucket1 VALUES(":ao.mos:pro:2", {"icc":2, "customerId":101});
INSERT INTO bucket1 VALUES(":pd:pro:1", {"icc":1});
INSERT INTO bucket1 VALUES(":pd:pro:2", {"icc":1});
INSERT INTO bucket1 VALUES(":pd:pro:3", {"icc":2});
Then inspect the documents you should have
:ao.mos:pro:1{"customerId":100,"icc":1}
:ao.mos:pro:2{"customerId":101,"icc":2}
:pd:pro:1{"icc":1}
:pd:pro:2{"icc":1}
:pd:pro:3{"icc":2}
Deploy the Eventing function and look at your documents again.
:ao.mos:pro:1{"customerId":100,"icc":1}
:ao.mos:pro:2{"customerId":101,"icc":2}
:pd:pro:1{"icc":1,"customerId":100}
:pd:pro:2{"icc":1}
:pd:pro:3{"icc":2}
As expected only one doc with matching keys and matching icc properties updated.
For more performance (doing millions) you can up the workers in the functions settings to 2x the physical cores.
I am trying to use FullCalendar v4 and cannot post data to MySQL. I have narrowed the problem down to $start and $end having UTC on the end and MySQL won't take it even though my datatype is TIMESTAMP. If I manually assign standard datetime data (without UTC) to $start and $end it will post to table. I have the statements commented out in the event.php that work, by overriding the data in the $POST.
My thought is I have something askew in MySQL that is causing the TIMESTAMP datatype to actually be a DATETIME datatype. I have deleted and created the table with SQL Statement shown below.
Running -> MySQL 8.01.5, Windows Server 2016, PHP 7.2.7, using jQuery
...
CREATE TABLE calendarsystem.events (
id int(11) NOT NULL AUTO_INCREMENT,
title VARCHAR(45) NOT NULL ,
start TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
end TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
resourceId VARCHAR(45) NOT NULL ,
PRIMARY KEY (id)
);
...
The code to add_event.php:
<?php
$title = $_POST['title'];
$start = $_POST['start'];
$end = $_POST['end'];
$resourceId = $_POST['resourceId'];
//$title = 'wtf';
//$start = '2019-03-25 16:00:00';
//$end = '2019-03-25T17:00:00';
//$resourceId = 'b';
try {
require "db_config.php";
} catch(Exception $e) {
exit('Unable to connect to database.');
}
$sql = "INSERT INTO events (title, start, end, resourceId) VALUES (:title, :start, :end, :resourceId )";
$q = $bdd->prepare($sql);
q->execute(array(':title'=>$title,':start'=>$start,':end'=>$end,':resourceId'=>$resourceId));
?>
...
If I open MySQL Workbench and try to add the data with the UTC copied from the output window of chrome I get the following error when applying:
Operation failed: There was an error while applying the SQL script to the database.
Executing:
INSERT INTO calendarsystem.events (start, end, title, resourceId) VALUES ('2019-03-25T14:00:00-05:00', '2019-03-25T15:00:00-05:00', 'xxx', 'b');
ERROR 1292: 1292: Incorrect datetime value: '2019-03-25T14:00:00-05:00' for column 'start' at row 1
SQL Statement:
INSERT INTO calendarsystem.events (start, end, title, resourceId) VALUES ('2019-03-25T14:00:00-05:00', '2019-03-25T15:00:00-05:00', 'xxx', 'b')
Sorry the post formatting is crappy
I think MySQL isn't recognizing the 'T' character or the trailing time offset in the string value.
'2019-03-25T15:00:00-05:00'
^ ^^^^^^
One way to fix the problem would be to remove that T character and the offset
'2019-03-25 15:00:00'
^
We expect MySQL to recognize a string in that format.
Alternatively, we could use STR_TO_DATE function with appropriate format model so MySQL can interpret datetime/timestamp values from strings in different formats.
The relevant topic in the MySQL Referenced Manual is here:
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html
I'm trying to store a percentage value in a MySQL database but when ever I try and set the value of the percentage column to 100%, I get an "Out of range value" error message.
I am currently using a DECIMAL(5,2) type and I need to be able to store values from 0% up to 100% (with 2dp when the value isn't an integer) ( the values are being calculated in a php script).
All values are fine apart from 100% which triggers the error.
Am I misunderstanding something or is there something else I am missing?
EDIT: The table was created using the following sql
CREATE TABLE overviewtemplate
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
numberOfTests INT NOT NULL DEFAULT 0,
description VARCHAR(255) NOT NULL DEFAULT "Please add a Description",
percentageComplete DECIMAL(5,2),
numberPassed INT NOT NULL DEFAULT 0,
numberFailed INT NOT NULL DEFAULT 0
) ENGINE=MYISAM;
EDIT 2: This is the code of the SQL query
$numberOfPasses = 5;
$numberOfFails = 5;
$percentageComplete = 100.00;
$sqlquery = "UPDATE `overviewtemplate`
SET numberPassed = {$numberOfPasses},
numberFailed = {$numberOfFails},
percentageComplete = {$percentageComplete}
WHERE description = '{$description}'";
EDIT 3: FIXED - Had a syntax error in my table names which meant it was trying to update a wrong table.
With your declaration you should be able to save even 999.99 without trouble. Check if you have set any rule for it not be bigger than 100? If yes then set it to be less than or equal to 100.00
It could be in a trigger.
I am using an Insert trigger on a table where I copy one record from one table to another.
Everything is ok. It works fine except on datetime columns. When I add a datetime column into the inserted values, then I get an error:
Invalid column name
My code is
ALTER TRIGGER [dbo].[Insert_MoinitoringBasic]
ON [dbo].[M0_BasicInfo]
FOR INSERT
AS
BEGIN
MERGE [MonitoringROSCII].[dbo].[MonitorBasicInfo] AS d
USING (SELECT DistrictID, upazilaID, LC_ID, AcademicYear, Trimester, RepID,
CASE VisitType
WHEN 'Initial validation' THEN 1
WHEN 'Full validation' THEN 2
WHEN 'Compliance monitoring' THEN 3
END AS VisitTp
FROM INSERTED) AS s ON s.DistrictID = d.DistrictID
AND s.upazilaID = d.upazilaID
AND s.LC_ID = d.LCID
AND s.AcademicYear = d.LCVisitYr
AND s.Trimester = d.Trimister
AND s.RepID = d.MOID
AND s.VisitTp = d.VisitType
WHEN MATCHED THEN
UPDATE
SET DistrictID = S.DistrictID
WHEN NOT MATCHED THEN
INSERT (DistrictID, UpazilaID, LCID, VisitType, LCVisitYr, Trimister, MOID,
LCStatus, IfCloseWhy, OthersSpecify,LC1stVstDt)
VALUES (DistrictID, UpazilaID, Lc_ID, VisitTp, AcademicYear, Trimester, RepId,
2, 'No', 'No', FirstVisitDate);
END
Here the last line FirstVisitDate which is a datetime column. Without this column, it worked nice but when I include this column, it shows the error mentioned above.
Can anybody help me with this?
Thanks
As the error text suggests, you are refering to a column that does not exist.
In the SELECT part of your MERGE statement, there is no output column named FirstVisitDate, which is why you're getting the error...
Is it safe to use the following code to prevent race conditions? (key and status fields and mysql_affected_rows are used to implement locking)
$mres = mysql_query("SELECT `values`, `key`, `status`
FROM `test`
WHERE `id` = 1");
$row = mysql_fetch_array($mres);
if($row['status'] != UPDATING) {
$mres = mysql_query("UPDATE `test` SET
`status` = UPDATING,
`key` = `key` + 1
WHERE `id` = 1 AND `key` = ".$row['key']);
if($mres && mysql_affected_rows()) {
//update here safely and then...
mysql_query("UPDATE `test` SET
`status` = NOT_UPDATING,
`key` = `key` + 1
WHERE `id` = 1");
}
}
My test shows that either it is not safe or I should search for a well-hidden mistake in my code.
Table is MyISAM
You should "acquire the lock" first before you retrieve values. Otherwise they may change before you get the lock.
$mres = mysql_query("UPDATE `test` SET
`status` = 'UPDATING'
WHERE `id` = 1 AND `status` = 'NOT_UPDATING'");
if ($mres && mysql_affected_rows()) {
// got the lock
// now select and update
}
id better be a unique field in the db or things may behave very weird
I couldn't see a reason to increment key
notice I quoted the strings 'UPDATING' and 'NOT_UPDATING' in sql
in your code, you should have also checked that $row['status'] had a meaningful value(what if it was false/null?) before comparing to the php constant UPDATING
hopefully you understand enough php to know that php strings should be quoted.
You can check for GET_LOCK and RELEASE_LOCK functions in MySql to simulate row locks.
http://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html#function_get-lock
With this approach you don't need to update rows. Also with mysql_affected_rows() if something goes wrong you may finish with always locked row (for example if you script crash before releasing row by updating it status to NOT_UPDATING). Locks granted with GET_LOCK are released automatically when connection is terminated.