CodeIgniter/sqlsrv/MSSQL Update-Queries contain Id-column - Error - php

I have a hard time migrating a WebApp from a Unix/Apache/MySQL System to Win2012/Apache/MSSQL. First I installed the sqlsrv-stuff you need and the connection works.
BUT:
update queries cause error mesages like
A Database Error Occurred
Error Number: 42000/8102
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Die
id-Identitätsspalte kann nicht aktualisiert werden." The last part
basically means "The ID-identy column may not be updated."
The generated update-query looks like this:
UPDATE "dbo"."table" SET "id" = 1, "someStuff" = 5 WHERE "id" = 1
My models use statements like:
$data = array (
'someStuff' => (int) $stuff
);
$this->db->update('table',$data,"id = ".$itemID);
I understand the message as the statement contains a SET "id" which is obviously irrelevant as the id-field is an auto-increment thing generated in mssql - and as you see, I am not including it in my model. How do I get Codeigniter to reduce the UPDATE-statement to not contain primary keys? Or is there another easy way to resolve this?
If it helps, I might as well modify Codeigniter to check if the internally generated query contains an id field in order to skip these, as they are always auto-incremented primary keys, but my attempts to do so weren't successful.

If id is an auto-increment field, don't include it in the Codeigniter Insert/Update query. It should be added automatically. Just Insert/Update the other values on the DB
Rem: Auto-increment attribute is set on the Database level not on the Codeigniter.

As I found out, someone made undocumented last-minute changes during the migration and found out that the data-array did not contain the id - and for a reason I'll never understand he thought it would be a great idea to put them in.
Sorry sorry for the confusion!
Lessons learned:
CI works fine even with SQLSRV,
I'll have to make sure that the code I create is uploaded as I wanted it to be.

Related

How to make MySQL strict on types

Here's the scenario, we are building a web application in Laravel, and assigned a route as follows:
Route::get('/sample/{client}', 'SampleController#SampleMethod')->name('SampleNaming');
The method SampleMethod, reads from the client variable and displays data about the client in the page.
if we go to http://localhost/appurl/sample/1 for example, it displays data about client id 1. The trick is that if we go to http://localhost/appurl/sample/1abc , it will still display the data for client id 1.
Tried the query in MySQL,
select * from clients where ID = '1abc'
The ID column is an integer and the primary key of the clients table.
The above query gave me the result for Client ID 1, turns out that MySQL checks the provided string and searches for the integer part in it and fetches the rows accordingly.
Surely, we can escape this in PHP / Laravel however my question is, is there a way to make MySQL strict on such scenarios?
Pure Laravel solution is to use Regular Expression Constraints.
Route::get('/sample/{client}', 'SampleController#SampleMethod')
->name('SampleNaming')
->where(['client' => '[0-9]+']);
you probably need to change sql_mode setting for your server. you need to use strict mode.
enter link description here
preventing type casting is not configurable in mysql. mysql implicit type casting rules
you can use the cast function to solve the issue at the sql level
select * from t where cast(id as char) = "1abcd"

How do I PHP echo exactly what is stored in a MySQL field?

I feel like there is probably a very simple answer for this, but I've spent about 20 minutes searching and can't find anything.
Basically, I am using PHP to query a table and output the results as a list, using the primary key column (COL_1) of the table to create a link for each record that will bring the user to a detail page for that record. It works fine when the data in COL_1 is a straight-forward string such as "TEST". The edit link will then be detail.php?COL_1=TEST The detail page works by querying the database using the data passed by the link. So in this case it would do a select on the table where COL_1 = 'TEST' and return the correct record.
However, when new line characters are stored in COL_1 things get a bit complicated. For instance, if 'TEST\r\nTEST' is stored in COL_1, when the original query of the entire table is done, $row['COL_1'] for that line will give me 'TESTTEST', which gets passed to the detail page as detail.php?COL_1=TESTTEST, the detail page does a select on the table where COL_1 = 'TESTTEST', and it returns nothing.
However, if I manually link to detail.php?COL_1=TEST\r\nTEST the detail page will query on 'TEST\r\nTEST' and return the correct record.
So basically what I need is a way to do a query and have $row['COL_1'] return 'TEST\r\nTEST' instead of 'TESTTEST'. Does this make sense? How would I go about doing this?
As for why the table is set up like this, don't ask me. I didn't design it. I'd never design keys that can include line breaks like this. But I do have to interact with this table. Bah.
You should encode values that are passed in the URL:
echo urlencode("TEST\r\nTEST");
However, why would TEST\r\nTEST be a primary key? That's crazy. Maybe you need to rethink how you are doing things. Primary keys as integers work nicely.

DELETE query won't completely remove record

I have been building a simple message board script, and have started writing a script named delete.php, where the user can input his/her password to delete the message. The message is stored with 4 values: id, name, password, timestamp, message.
The problem I am having is the DELETE query I am using will not completely remove the record. It will remove the name and message fields, but the row still exists with id, timestamp and password. So on my messageboard, rather than the message being deleted, theres a blank message with a timestamp.
I can delete the entry in PHPMyAdmin, but it won't work from my PHP script.
$db_connection->query("DELETE FROM 'messages' WHERE 'id' = ".$m_id.";")
or die($db_connection->error);
$m_id stores the ID number of the message.
No errors are returned, and I cannot access the Apache error log.
It may well be the ";" which is hampering your query, at the end of your statement here:
("DELETE FROM 'messages' WHERE 'id' = ".$m_id.";")
And as noted in the comment section, table names do not need quotes around them
A typical DELETE statement should be composed of a simple query like this:
mysql_query("DELETE FROM messages WHERE id='$m_id'") or die(mysql_error());
Although, using mysql_ function would be a very bad idea, since they are deprecated/not maintaned. In which case, you should learn PDO / mysqli
Try:
$db_connection->query('DELETE FROM messages WHERE id = ' . $m_id ) or die($db_connection->error);
If it doesn't work you can do 2 things:
1) Look at Apache's error log.
2) When you delete the row in PhpMyAdmin it often shows you the query used.
I looked at the screenshot you provided in the comments, and one possibility is that the existing record really is deleted, but a new one is added by a different piece of code. Without seeing all of your code, I can't tell if this is truly the case. It's something to look for, of course, in addition to making sure you don't have any triggers. Another possibility is that your delete statement isn't actually running at all, but another piece of code is updating that record and setting some of the columns to NULL/blank.

MySQL error after reordering ID column

I need some help with a particular table in my database. I tried reordering a column (id) of integers, but now the present values of renamed id are taking the values of the former value.e.g
If: (before re-odering)
------------
id Name
2 Stack
3 Over
4 Flow
------------
A link like page.php?id=3 gives a value of OVER which is correct
After re-numbering
------------
id Name
1 Stack
2 Over
3 Flow
4 Name
5 Last
------------
When I use a link like page?id=3 i still get OVER, which is not correct. Also the new id = 5 does not return any value.
Please where could the problem be ?
Update
When I tried from phpMyAdmin "SELECT * FROM tap_bios WHERE tap_bios_id = 3 I get Over instead of Flow.
...are you sure you don't have that request cached in your browser? Try clearing the cache and rerunning the query. Also, try logging the queries and copy/pasting them into a query browser. If you get the same unexpected results when dealing directly with the database while using the queries you think are correct, it's a database issue that will require further investigation. Otherwise, you may have a caching issue happening somewhere else in the system.

MSSQL ERROR "Invalid object name" when I add a field to the query?

I have an INSERT query that works fine, but when I add an extra field I get the oh-so-helpful:
Invalid object name 'optimizations'
Optimizations being the table name. The query is below... I am totally lost as to why this wouldn't work. If I cut & paste the query into MSSQL Management Studio, the query works fine.
INSERT INTO [optimizations]
([opt_date],[opt_concept_id],[opt_pallet],[opt_turnable],
[opt_sideupok],[opt_endupok],[opt_flatok],[opt_notstickingout],
[opt_notinoverhang],[opt_itemsloaded],[opt_loadedweight],
[opt_pweightutil],[opt_pvolumeutil],[opt_request_xml],
[opt_response_xml],[opt_images],[opt_primary_stage_id])
VALUES
(GETDATE(),'775','20ft','true','false','false','true',
'true','true','10','5952.6','18.6','48.9',
'<xml><herpa><derpa>xml</derpa></herpa></xml>',
'<xml><herpa><derpa>xml</derpa></herpa></xml>',
'img1.jpg,img2.jpg,img3.jpg','98');
For some reason, if I include the last field in the query [opt_primary_stage_id] it does not work... if I omit this field it works fine. Interestingly enough if I add [opt_primary_stage_id] to the list of fields being passed, and pass it a value of NULL the query also works fine. The [opt_primary_stage_id] field's data type is INT, I have tried including the last entry of the VALUES() section both as a straight number (3) and with quotes ('3')... neither works.
The server executing the code is running PHP 4.3.9, under IIS and with and MSSQL.
This is a version of the query, with the SAME data that will work.
INSERT INTO [optimizations]
([opt_date],[opt_concept_id],[opt_pallet],[opt_turnable],
[opt_sideupok],[opt_endupok],[opt_flatok],[opt_notstickingout],
[opt_notinoverhang],[opt_itemsloaded],[opt_loadedweight],
[opt_pweightutil],[opt_pvolumeutil],[opt_request_xml],
[opt_response_xml],[opt_images])
VALUES
(GETDATE(),'775','20ft','true','false','false','true','true',
'true','10','5952.6','18.6','48.9',
'<xml><herpa><derpa>xml</derpa></herpa></xml>',
'<xml><herpa><derpa>xml</derpa></herpa></xml>',
'img1.jpg,img2.jpg,img3.jpg');
EDIT: Fixed XML to have proper bracketing & added working query.
Adding a field won't cause failure on it's own: there is a valid reason.
You say it runs in SSMS OK then it shows that issue is in PHP or in the call.
First thoughts:
How long is the command. Is it being truncated somewhere in PHP? Is this dynamic SQL IRL?
Is the user context the same from the client? You may have the same table in 2 different schemas for example, with differing permissions.
Wrong database in the connection. What does SELECT DB_NAME() say? Sounds obvious but no object = not there. Don't dismiss this idea and assume it is the correct context: check.

Categories