INSERT INTO with subquery & parameters not working in MS-Access - ms-access

I have an INSERT INTO which works fine with the parameters as constants:
INSERT INTO FinalValidityCodes
(tblReceivedSamplersID, Substudy, Location, FinalValidityCode, DateTimeProcessed)
SELECT ID, true, 'I', 0, now()
FROM tblReceivedSamplers
WHERE (SampleID = ?)
This would affect 1 row (as expected)
Yet if I change the query to use parameters it will allow it to run but will never affect any rows.
INSERT INTO FinalValidityCodes
(tblReceivedSamplersID, Substudy, Location, FinalValidityCode, DateTimeProcessed)
SELECT ID, ?, ?, ?, ?
FROM tblReceivedSamplers
WHERE (SampleID = ?)
What is the difference and why, when I use parameters, does the Insert, seemingly, fail?
Edit:
SampleID is a text datatype.

It looks like the purpose of that INSERT is to add a single row to FinalValidityCodes with values for 5 fields. However, 4 of those values will be supplied directly by query parameters, and ID/tblReceivedSamplersID will be derived from another parameter.
So I would try a DLookup() expression to get the ID (using the parameter for SampleID), and insert that value along with the other 4 parameter values. Here is an untested guess.
INSERT INTO FinalValidityCodes (
tblReceivedSamplersID,
Substudy,
Location,
FinalValidityCode,
DateTimeProcessed
)
VALUES (
DLookup("ID", "tblReceivedSamplers", "SampleID ='" & param1 & "'"),
param2,
param3,
param4,
param5
);

Related

WRONG_VALUE_COUNT_ON_ROW: But I can't see the problem?

I'm trying to insert data into MySQL via Express, the database table is created as such:
create table foods (name VARCHAR(100), typval DECIMAL(8, 2), unit VARCHAR(50), calories DECIMAL(5, 2), carbs DECIMAL(5, 2), fat DECIMAL(5,2), protein DECIMAL(5, 2), salt DECIMAL(5, 2), sugar DECIMAL(5, 2));
I have a form which collects user data and the function to post looks something like this:
app.post("/addnewfood", function (req,res) {
console.log(req.body.name, req.body.typval, req.body.unit, req.body.calories, req.body.carbs, req.body.fat, req.body.protein, req.body.salt, req.body.sugar);
// saving data in database
let sqlquery = "INSERT INTO foods (name, typval, unit, calories, carbs, fat, protein, salt, sugar) VALUES (?,?)";
// execute sql query
let newrecord = [req.body.name, req.body.typval, req.body.unit, req.body.calories, req.body.carbs, req.body.fat, req.body.protein, req.body.salt, req.body.sugar];
db.query(sqlquery, newrecord, (err, result) => {
if (err) {
return console.error(err.message);
}else
res.send("New" + " " + req.body.name + " was added to the database.");
});
});
I'm not sure where I'm going wrong since I counted there's 9 different fields I need to fill in for the 9 different columns. I've checked the commas and I can't see anything out of place.
When I try to enter data like: "McDonalds Hamburger, 1.0, Burger, 100.00, 10.00, 10.00, 10.00, 1.0, 10.00"
The console.log prints it out fine and it should work however, I get:
ER_WRONG_VALUE_COUNT_ON_ROW: Column count doesn't match value count at row 1
Help?
Your INSERT query needs a placeholder for every column you insert. You only have two placeholders -- two ? items -- here.
VALUES (?,?)
You need nine, one for each column.
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)

Coalesce not working in insert statement for a null table

I am trying to use the coalesce function in SQL to avoid getting an error when inserting a row with an auto-incrementing uid into a table that is null. However, the following code is still giving me:
"cannot insert the value null into column 'TABLE_ONE_UID'".
cmdEx.ExecuteNonQuery(
"INSERT INTO TABLE_ONE
(TABLE_ONE_UID, USER_UID, SHT_DATE,
C_S_UID, CST_DATE,
CET_DATE, S_M, PGS)
VALUES ((SELECT MAX(COALESCE(TABLE_ONE_UID, 0)) + 1
FROM TABLE_ONE),
127, '2009-06-15T13:45:30',
0, '2009-06-15T13:45:30','2010-06-15T13:45:30',
'TEST DELETE THIS ROW', 0 )");
The correct way to solve this is with an auto_increment column:
create table PMS_CALC_SCHEDULE (
PMS_CALC_SCHEDULE_UID int auto_increment primary key,
. . .
);
If, for some reason, you want to do the calculation yourself, subject your code to race conditions, and have slower inserts, then you need to do the coalesce in the right place:
INSERT INTO PMS_CALC_SCHEDULE (PMS_CALC_SCHEDULE_UID, . . .)
SELECT COALESCE(MAX(PMS_CALC_SCHEDULE_UID), 0) + 1,
. . .
FROM PMS_CALC_SCHEDULE ;
This would happen when your source table doesn't have any row, MAX would return null in this case.
To prevent this, you can use interchange COALESCE and MAX, e.g.:
INSERT INTO PMS_CALC_SCHEDULE
(PMS_CALC_SCHEDULE_UID, USER_UID, SCHEDULED_DATE,
PMS_CALC_STATUS_UID, CALCULATION_START_DATE,
CALCULATION_END_DATE, STATUS_MESSAGE, PROGRESS)
VALUES ((SELECT COALESCE(MAX(PMS_CALC_SCHEDULE_UID), 0) + 1
FROM PMS_CALC_SCHEDULE),
127, '2009-06-15T13:45:30',
0, '2009-06-15T13:45:30','2010-06-15T13:45:30',
'TEST DELETE THIS ROW', 0 )")
Here's the SQL Fiddle.
If the field is set to AutoIncrement on the table itself, just leave the field out of your Insert-Statement. The value is added by the database itself.

SSRS 2008 R2 - all parameters multi value AND optional

I've got a report that has 6 parameters. All parameters need to be optional and 3 have to be multi-value. One of the optional parameters is a dropdown, the rest are manually keyed in text boxes.
The Where clause below works when there are multiple #VendorNum values and one #FullJA value, but fails with multiple #FullJA values regardless of the #VendorNum count.
Parameters:
#VendorNum - keyed manually by user (space delimited) - optional, can be multivalue
#FullJA - keyed manually by user (space delimited) - optional, can be multivalue
#BU - optional, can be multivalue - when #JA is populated, this will auto-populate, if #JA isn't populated it's a dropdown with all selected.
#JA3 - keyed by user - optional, single value
#StartDate and #EndDate - optional single values
select * from some_table
WHERE
/*FULL JA*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEFT(JA, 7) IN (#FullJA)
AND BU IN(#BU)
AND #JA3 IS NULL
)
OR
/*DATE RANGE*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEN(ISNULL(CONVERT(VARCHAR(20), Cleared_When), '0')) >= #ClearedOnly
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND BU IN (#BU)
AND #FullJA IS NULL
AND #JA3 IS NULL
)
/*BUS UNIT AND JA3*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND LEFT(JA, 3) = (#JA3)
AND #FullJA IS NULL
)
/*BUS UNIT ONLY*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND #JA3 IS NULL
AND #FullJA IS NULL
)
The dataset parameter values for #FullJA and #VendorNum are both
=IIF(InStr(Parameters!FullJA.Value," ")>0,SPLIT(Parameters!FullJA.Value," "),Parameters!FullJA.Value) and all params are set as NOT multivalue, with nulls allowed.
Any help would be greatly appreciated. I've written over 200 reports for this project and this is the only one that is really grinding my gears!
Thanks!
I would approach this by building up some temp tables / table variables, to hold the potentially multi-valued variables, and then joining to those tables. This has the advantage of you being able to insert all possible values, in the case they have omitted the variable. So, you'd split your strings and put them into those tables (something along the lines of this example) if given the variable, and otherwise just do an insert into to populate your temp table / table variable.
For a split function, I prefer something like this:
create FUNCTION [dbo].[Split] (#sep VARCHAR(32), #s VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT r.value('.','VARCHAR(MAX)') as Item
FROM (SELECT CONVERT(XML, N'<root><r>' + REPLACE(REPLACE(REPLACE(#s,'& ','& '),'<','<'), #sep, '</r><r>') + '</r></root>') as valxml) x
CROSS APPLY x.valxml.nodes('//root/r') AS RECORDS(r)
)
GO
GRANT SELECT
ON OBJECT::[dbo].[Split] TO PUBLIC
AS [dbo];
I would then put those variables into a table using something like this (my separator is a ", "):
select ltrim(rtrim(ppl.Item)) as PersonName
into #gppl
from dbo.Split(', ', #PersonListForCompare) as ppl
You would do something more like:
select ltrim(rtrim(vnd.Item)) as VendorNum
into #vendorNums
from dbo.Split(', ', #VendorNum) as vnd
You would then join to that temp table just like any other table & use it to limit your results that way. In your case, you want to put in all vendors (possibly) if they didn't give you any input. So, you'd do something like:
create table #vendorNums (VendorName varchar(64)) --I have no idea, here, what this data looks like
if #VendorNum is not null and datalength(#VendorNum) > 0
insert into into #vendorNums (VendorNum)
select ltrim(rtrim(vnd.Item))
from dbo.Split(', ', #VendorNum) as vnd
else
insert into into #vendorNums (VendorNum)
select VendorNum
from dbo.Vendors
That said, I think that you could use your select from dbo.Split directly as a table in a join, rather than putting it into the temp table. Only problem would be you'd have to be sure you had data in there to split, or else you're going to have a bunch of combinations to get the right match-up of null parameters vs. filled ones.

How to insert record if there are no duplicate in the previous query in MySQL

I have 2 insert queries that I need to execute. each query will insert data in a different table. The first query has ON DUPLICATE KEY UPDATE clause. What I need to do is to prevent the second query from running is the first one cause an update due to a DUPLICATE KEY.
here is my code currently.
$insertEvent = $db->processQuery('INSERT INTO calendar_events (start_on, end_on, subject, owner_id, created_by, phone_call_id, status )
VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE start_on = ?, end_on =?, status = ? ',
array($start, $end, $subject, $owner, $created_by, $phone_call_id, $status, $start, $end, $status) );
$event_id = $db->lastinsertid();
$insertEvent2 = $db->processQuery('INSERT INTO calendar_attendees (event_id, owner_id) VALUE (?, ?)', array($event_id, $owner));
I only want to execute $insertEvent2 only if $insertEvent created a new record otherise ignore the second statement.
Thanks
I believe you can use INSERT IGNORE syntax on your second INSERT, so that your query will look like
INSERT IGNORE INTO calendar_attendees (event_id, owner_id) VALUES (?, ?)
Make sure that you have a UNIQE constraint on (event_id, owner_id).
BTW you have a typo in your second insert. It should be VALUES instead of VALUE.

MySQL performing math operations on strings?

I am trying to store latitude and longitude information in MySQL. I am using Ruby to parse the latitude and longitude data. They are parsed separately and then combined into a string variable. So if I have:
latitude = 43.78219.to_s
longitude = -75.00326.to_s
location = latitude + " " + longitude # => "43.78219 -75.00326"
I have a table in MySQL to store this data, and the data type is set to String varchar. The problem is that when I insert the location string into the table, MySQL performs a math operation and subtracts the two numbers in the string. Then I'm like Whaaaaaaaaa???????
So it ends up storing -31.22107 as the location. Am I doing something wrong?
Here is the query I'm using
db.query("insert into StationCapacityStatus
(city_id, station_id, location, empty_docks, nonempty_docks, timestamp)
values(
23,
#{$station_number},
#{location},
#{$empty_docks},
#{$nonempty_docks},
#{$datetime}
)"
)
You're not quoting the location so MySQL's sees a plain 43.78219 -75.00326 inside the VALUES and interprets it as a floating point expression. You should use quote method to properly escape the strings as well:
db.query("insert into StationCapacityStatus
(city_id, station_id, location, empty_docks, nonempty_docks, timestamp)
values(
23,
#{$station_number},
'#{db.quote(location)}',
#{$empty_docks},
#{$nonempty_docks},
#{$datetime}
)"
)
You should also switch to prepared statements with bound values if possible:
sth = db.prepare('insert into StationCapacityStatus (city_id, station_id, location, empty_docks, nonempty_docks, timestamp) values (?, ?, ?, ?, ?, ?)')
sth.execute(23, $station_number, location, $empty_docks, $nonempty_docks, $datetime)