The SQL Server code below returns the time-date of the last update to a table (any row.)
SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update
FROM sys.dm_db_index_usage_stats
WHERE OBJECT_ID=OBJECT_ID('TableName')
AND (Index_ID = 1)
If I use this in a TFDQuery, what is the datatype FDQuery1.FieldByName('last_user_update')?
If I want to store and compare this value at different times in a Delphi variable, what Delphi datatype should I assign it to, Double?
You use a TDateTime for this.
Although the TDateTime is represented internally by a double you don't use a double because you'll miss out on all the date/time support.
The code goes like this.
var
LastUpdate: TDateTime;
begin
//Do query etc.
...
LastUpdate:= MyQuery.FieldByName('last_user_update').AsDateTime;
Note that SQL server 7 and before do not have support for TDate. So if you just want the date part this code will fail in SQL server 7.
LastUpdate:= MyQuery.FieldByName('last_user_update').AsDate;
Just get the full DateTime and strip of the Time part later.
However, you're working with 2008 so just extracting the date will work fine for you.
Here's a list of DateTime functions: http://www.delphibasics.co.uk/ByFunction.asp?Main=DatesAndTimes
I'm auditing a project and I found a way to inject data in a query.
The project uses Hibernate and for this piece of code Session.createSqlQuery() and then a .list()
The SQL is something like : "SELECT * FROM tablename ORDER BY column XXXXXX"
XXXXXX can be modified using Fiddler. So I tried
SELECT * FROM tablename ORDER BY column DESC; truncate table tablename;
Unfortunately (well only for my injection attempt) it's not working and I'm getting :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'truncate table tablename'
My question is, since they're using createSQLQuery, are they safe from injection. If they're not, could you give me an example to highlight the issue.
I tried using %08 (Backspace character) thinking I would be able to delete previous query characters for example (It didn't work ;) )
Thanks.
After some research it seems I won't be able to modify data with this security hole, however using ORDER BY (CASE WHEN ...) would allow to "scan" the tables and the data.
Is the column name specified using a parameterized statement or are you just concatenating text?
ex: in perl::DBI, the drivers support the following syntax:
$dbh->do("SELECt * FROM asdf ORDER BY ?", undef, $order_by);
The ? there is a form of parameterized statement which sanitizes the input automatically.
I've searched and can't seem to find quite what I'm looking for.
I'm running a PL/SQL script in Oracle, and attempting to insert records into a table in MySQL via database link using MySQL ODBC 5.2 Unicode Driver.
The link works fine, I can do complex queries in Oracle using it, and do various inserts and updates on records there.
Where it fails is in trying to insert a record into a MySQL table that has a column of type bit(1).
It is basically a cursor for loop, with the insert statement looking something like:
INSERT INTO "app_user"#mobileapi (USERNAME, VERSION, ACCOUNT_EXPIRED, ACCOUNT_LOCKED, PASSWD, PASSWORD_EXPIRED)
VALUES (CU_rec.USERNAME, CU_rec.VERSION, CU_rec.ACCOUNT_EXPIRED, CU_rec.ACCOUNT_LOCKED, CU_rec.PASSWD, CU_rec.PASSWORD_EXPIRED)
Some of the target columns, like ACCOUNT_EXPIRED, ACCOUNT_LOCKED, etc. are the bit(1) columns in MySQL. Given that I can convert the data types in the cursor CU_rec to pretty much anything I want in Oracle, how can I get them inserted into the target? I've tried everything I can think of, and I just keep getting:
Error report:
ORA-28500: connection from ORACLE to a non-Oracle system returned this message:
[MySQL][ODBC 5.2(w) Driver][mysqld-5.6.10]Data too long for column 'ACCOUNT_EXPIRED' at row 1 {HY000,NativeErr = 1406}
ORA-02063: preceding 2 lines from MOBILEAPI
ORA-06512: at line 44
28500. 00000 - "connection from ORACLE to a non-Oracle system returned this message:"
*Cause: The cause is explained in the forwarded message.
*Action: See the non-Oracle system's documentation of the forwarded
message.
Any help at all would be greatly appreciated.
Your problem is Oracle's default datatype conversion over ODBC; according to their own documentation they convert SQL_BINARY to a raw. Although not directly related, Oracle's comparison of MySQL and Oracle within SQL Developer also alludes to the fact that the automatic conversion from a MySQL bit is to an Oracle raw.
Extremely confusingly, MySQL's documentation indicates that a bit is converted to a SQL_BIT or a SQL_CHAR, which implies that it may work in the other direction1.
According to Microsoft's ODBC docs you should, theoretically, be able to use the CONVERT() function to transform this into a character, which should, theoretically, be translatable by MySQL.
insert into some_table#some_db (bit_col)
values( {fn convert(some_col, SQL_CHAR)} );
Failing that there's another couple of options, but it does depend on what you're attempting to insert into the MySQL database from Oracle and what the datatype is in Oracle. For instance you could use the Oracle CAST() function to convert between datatypes. For instance, the following would convert an integer to a binary double.
select cast(1 as binary_double) from dual
Unfortunately, you can't cast an integer to a raw, only a character or a rowid, so in order to convert to a raw you'd have to do the following:
select cast(to_char(1) as raw(1)) from dual
I've no idea whether MySQL will accept this but with some testing you should be able to work it out.
1. For clarity, I've never tried it in either direction.
Hah! I found a solution. Dropping it here in case it helps someone else. It's not pretty, but it works.
I used the old EXECUTE IMMEDIATE trick.
Basically, I created a variable sql_stmt varchar2(4000) and wrote code like:
sql_stmt := 'insert into "app_user"#mobileapi (USERNAME, VERSION, ACCOUNT_EXPIRED, ACCOUNT_LOCKED, CIPHER_PASSPHRASE, ENABLED, PASSWD, PASSWORD_EXPIRED)
values ('''||CU_rec.USERNAME||'','||CU_rec.VERSION||', '||CU_rec.ACCOUNT_EXPIRED||', '||CU_rec.ACCOUNT_LOCKED||', '''||CU_rec.CIPHER_PASSPHRASE||''', '||
CU_rec.ENABLED||', '''||CU_rec.PASSWD||''', '||CU_rec.PASSWORD_EXPIRED||')';
EXECUTE IMMEDIATE sql_stmt;
Something like that anyway (the quotes might not line up, as I hacked this a bit from the actual code). Looking at the contents of sql_stmt, I get:
insert into "app_user"#mobileapi (USERNAME, VERSION, ACCOUNT_EXPIRED, ACCOUNT_LOCKED, CIPHER_PASSPHRASE, ENABLED, PASSWD,PASSWORD_EXPIRED)
values ('user#email.com', 0, 0, 0, 'asdfastrwaebawavgansdhnsgjsjsh', 1, 'awercbcakwjerhcawuerawieubkahbewvkruh', 0)
The EXECUTE IMMEDIATE completes, and checking the target table, the values are there.
Possibly a crappy solution, but better than nothing.
I am using sql server database drivers in codeigniter and I am executing the following query:
select A.inst_name,Substring((Select ',' + cast(B.program_id as varchar(15))
From k12_dms_inst_programs B
Where B.inst_id=A.id For XML Path('')),2,8000) As EmployeeList
From k12_dms_institution_master A
Group by A.inst_name,A.id
which is working absolutely fine in SSMS.
But when I am trying to execute the same query using Codeigniter I am getting the following error:--
Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier.
Found some solutions on php.net
MSSQLNewbie 19-Sep-2011 06:34
In /etc/freetds/freetds.conf add these two lines (last two):
[global]
;tds version = 4.2
tds version = 8.0
client charset = UTF-8
You can edit "charset" in php.ini too (but you don't need if you did it previously in freetds.conf):
; Specify client character set..
; If empty or not set the client charset from freetds.comf is used
; This is only used when compiled with FreeTDS mssql.charset = "UTF-8"
Use nchar/nvarchar/ntext column types if you need unicode support.
dann dot farquhar at iteams dot org 24-Sep-2009 11:45
I found that changing the version in /etc/freetds.conf from 4.2 to 8.0
fixes this problem without having to make any changes to the SELECT
statement
huberkev11 at hotmail dot com 12-May-2006 01:47
This is because you are using column types of like ntext instead of
text. There are 2 solutions.
1 Change all ntext column types to text or
2 Your query must look like: SELECT CAST(field1 AS TEXT) AS field1 FROM table
Hope they will help.
I am using Visual Foxpro 9 with SQL Server as back-end. I am executing this query to update an existing column value with a unicode text:
UPDATE <table> SET fname = "N('" + hexchr + "')"
The problem is Foxpro is storing string as:
N(0945;0987;)
whereas when the same command is run via SQL Server management studio, the string is stored as actual devnagari font.
How to make Foxpro execute the above query with the N?
I've never tried working with Unicode and feeding SQL-Server... However, with respect to helping prevent SQL-Injection, in VFP, when using SQL-Passthrough (SQLConnect(), SQLExec(), etc), If you write your query with "?" place-holder, it will look at the VARIABLE from within VFP... such as
myField = 0x123 && or whatever hex value... VFP leading with 0x implies hex
myKey = "whatever"
cSQLCmd = "update SomeTable set Field1 = ?myField where SomeKey = ?myKey"
nSQLHandle = sqlconnect( YourConnectionStringInfo )
SQLExec( nSQLHandle, cSQLCmd )
sqldisconnect( nSQLHandle )
VFP will handle the ? parameters for you by their respective found variable names that are available. Now, all that being said, VFP was only based on 32 bit, and don't believe it recognizes "unicode" values. What you may need to do is create a stored procedure in SQL that accepts two hex value (or whatever), and call that and pass it in as so required.