How to connect Oracle database 11g Server on FoxPro 9 - oracle11g

How to connect remote oracle database 11g server in FoxPro?

It should be relatively simple provided you have the data provider installed.
I would start by looking at the connection string requirements
With that, you can get a handle to the database via
cConnectionString = "Driver = blah;Server=blah; etc from connection string website reference";
nHandle = SQLStringConnect( cConnectionString )
if nHandle < 1
messagebox( "Unable to connect" )
return
endif
*/ Once connected, you can then query the database
nResult = SQLExec( nHandle, "select * from yourTable", "cursorResultSentBackToVFPSide" )
if nResult < 1
messagebox( "Error querying data" )
return
endif
*/ If you need to parameterize something, a local variable in your routine can be used
*/ and will be applied by using the "?" place-holder, such as
lnSomeIDYouWant = 1234
lcSQLCmd = "select * from SomeTable where SomeKey = ?lnSomeIDYouWant order by blah"
nResult = SQLExec( nHandle, lcSQLCmd, "C_VFPAlias" )
SQLDisconnect(nHandle)
The parameters can be of almost any type (except for things like general/binary which might need alternate measures, but the others like logical, numeric, date, string all no problems).

Related

Importing MS Access data into VFP

I need to import data from an Access app into VFP tables. I have found solutions on the net for reading VFP data into Access but not the opposite. The connection string suggested by MS* seems to be missing something because I keep getting a dialog box asking me for the type of the source data
"Microsoft.ACE.OLEDB.12.0;Data Source=MyAccessApp.accdb;Persist Security Info=False;"
I would be grateful for any suggestion and/or explanation.
/bernard
if you are writing the program within VFP, then you can do a connect from VFP to the Access Database without the use of a "DSN", but requires a full connection string setting. Once that is done, you can query the data down into a local VFP cursor, then do what you want once it is in VFP... copy to a VFP table, query subsets of data, add records to another VFP table by whatever criteria you need to process.
nAccessHandle = sqlstringconnect( "DRIVER=Microsoft Access Driver (*.mdb, *.accdb); DBQ=C:\YourFullPath\YourAccessDatabase.accdb;" )
if nAccessHandle < 1
messagebox( "Invalid connection to access database" )
return
endif
*/ Valid handle, now, query down the data to a local VFP cursor
nSQLAns = SQLExec( nAccessHandle, "select * from YourAccessTable", "C_CursorInVFP" )
if nSQLAns < 1
messagebox( "Unable to get any data..." )
sqldisconnect( nAccessHandle )
return
endif
*/ Done with connection
sqldisconnect( nAccessHandle )
select C_CursorInVFP
copy to C:\SomeOtherPath\NowItsAVFPTable
*/ Or, query from it within VFP or loop from it...
select C_CursorInVFP
scan
*/ Look for records in VFP to do/ignore as needed...
select * from SomeVFPTable ;
where SomeKey = C_CursorInVFP.KeyFromAccessTable;
into cursor C_WasItFound readwrite
if reccount( "C_WasItFound" ) > 0
*/ Do what if it WAS found
else
*/ Do what if it WAS NOT found
endif
endscan

How to display the highest value from a column in a sqlite database in lua corona

I'm creating a game and when it finishes it stores it in a database (code below that adds it)
-- open SQLite database, if it doesn't exist, create database
local path = system.pathForFile("leaderboards.sqlite", system.DocumentsDirectory)
db = sqlite3.open( path )
print(path)
-- setup the table if it doesn't exist
local tablesetup = "CREATE TABLE IF NOT EXISTS leaderboards (id INTEGER PRIMARY KEY, score INDEXED);"
db:exec( tablesetup )
print(tablesetup)
-- save student data to database
local tablefill = "INSERT INTO leaderboards VALUES (NULL,'" .. score .. "');"
print(tablefill)
db:exec( tablefill )
-- close database
db:close()
print("db closed")
Then I want at the top of the screen to display the highest score so this is my display function
local function highScore()
-- open database
local path = system.pathForFile("leaderboards.sqlite", system.DocumentsDirectory)
db = sqlite3.open( path )
print(path)
--print all the table contents
local sql = "SELECT MAX(score) FROM leaderboards"
local val = db:exec(sql)
local t = display.newText("Best: "..val, 300, -20, nil, 28)
print(val)
t:setTextColor(255,255,255)
db:close()
end
Right now on the screen it is just saying 0 and not the high score or any screen. The values are being entered in the database but my sql statement isn't displaying it.
The simplest method is
local val
for x in db:urows "SELECT MAX(score) FROM leaderboards" do val = x end
Or
local sql = "SELECT MAX(score) FROM leaderboards"
for val in db:urows(sql)
local t = display.newText("Best: "..val, 300, -20, nil, 28)
print(val)
t:setTextColor(255,255,255)
end
See the urows documentation here.
From the docs:
db:exec
db:exec(sql[,func[,udata]])
db:execute(sql[,func[,udata]])
Compiles and executes the SQL statement(s) given in string sql. The
statements are simply executed one after the other and not stored. The
function returns sqlite3.OK on success or else a numerical error code
(see Numerical error and result codes).
If one or more of the SQL statements are queries, then the callback
function specified in func is invoked once for each row of the query
result (if func is nil, no callback is invoked). The callback receives
four arguments: udata (the third parameter of the db:exec() call), the
number of columns in the row, a table with the column values and
another table with the column names. The callback function should
return 0. If the callback returns a non-zero value then the query is
aborted, all subsequent SQL statements are skipped and db:exec()
returns sqlite3.ABORT.
In your code, the local val receives sqlite3.OK, which probably equals 0. You need to provide a callback function to receive row data, for example
local function maxscorecb(udata, ncols, colvals, colnames)
--Assuming that it's always one row and value
udata[1] = colvals[1]
return 0
end
--print all the table contents
local sql = "SELECT MAX(score) FROM leaderboards"
local scoretab = {}
local val = db:exec(sql, maxscorecb, scoretab)
local t = display.newText("Best: "..scoretab[1], 300, -20, nil, 28)
print(val)
t:setTextColor(255,255,255)
db:close()
P.S. Haven't tested it, just based on reading the docs.

Do braces { } protect me from sql injection with a dynamic query in Oracle 11g?

Read this:
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
On the dynamic sql part it has various such as this:
So, if you had an existing Dynamic query being generated in your code that was going to Oracle that looked like this:
String query = "SELECT user_id FROM user_data WHERE user_name = '" + req.getParameter("userID")
+ "' and user_password = '" + req.getParameter("pwd") +"'";
try {
Statement statement = connection.createStatement( … );
ResultSet results = statement.executeQuery( query );
}
You would rewrite the first line to look like this:
Codec ORACLE_CODEC = new OracleCodec();
String query = "SELECT user_id FROM user_data WHERE user_name = '" +
ESAPI.encoder().encodeForSQL( ORACLE_CODEC, req.getParameter("userID")) + "' and user_password = '"
+ ESAPI.encoder().encodeForSQL( ORACLE_CODEC, req.getParameter("pwd")) +"'";
And it would now be safe from SQL injection, regardless of the input supplied.
But the later is says:
Oracle 10g escaping
An alternative for Oracle 10g and later is to place { and } around the string to escape the entire string. However, you have to be careful that there isn't a } character already in the string. You must search for these and if there is one, then you must replace it with }}. Otherwise that character will end the escaping early, and may introduce a vulnerability.
I did not see an example, but does this mean I can use braces instead of the Codec ORACLE_CODEC....etc.? Does anyone have an example? Thanks.
No, this is not an injection prevention technique. The only way to be 100% sure that you're not vulnerable to injection is to use prepared statements and bind parameters for all user input that needs to be inserted into the query. Anything less than that, and you're pretty much just rolling the dice.

Informix ODBC Query Appends Time on a date field

I have a .aspx page that has query to and informix database. This query is done via an odbc connection and is put into a datatable. Then this datatable is used as the datasource for a radio button group.
My problem is that for whatever reason the time is being appended to the radio button as "12:00:00 AM". This is odd because the informix field is a date field that does not include the time. If I were to run the query outside of the webpage it returns it without the time... "2012-06-15"
So in summary... what I am getting is: "6/15/2012 12:00:00 AM" and what I want is "06/15/2012"
The query is as follows:
"select DATE(attend_date) as attend_date from soar_major_table where major =? and active<>'N'"
The code that creates the datatable:
string connString;
connString = ConfigurationManager.ConnectionStrings [ "ERP" ].ConnectionString;
OdbcConnection conn = new OdbcConnection ( );
conn.ConnectionString = connString;
string sql = "select DATE(attend_date) as attend_date from soar_major_table where major =? and active<>'N' ";
OdbcCommand command = new OdbcCommand ( );
command.CommandText = sql;
command.Parameters.Add ( new OdbcParameter ( "major", major ) );
command.Connection = conn;
DataTable dt = new DataTable ( );
OdbcDataAdapter dataAdapter = new OdbcDataAdapter ( );
dataAdapter.SelectCommand = command;
try
{
conn.Open ( );
dataAdapter.Fill ( dt );
}
finally
{
if ( conn != null && conn.State == ConnectionState.Open )
{
command.Dispose ( );
dataAdapter.Dispose ( );
conn.Close ( );
}
}
return dt;
And lastly the population of the radio btn group:
if ( dt.Rows.Count > 0 )
{
rdoDate.DataSource = dt;
rdoDate.DataTextField = "attend_date";
rdoDate.DataValueField = "attend_date";
rdoDate.DataBind ( );
}
The problem is upstream of the Informix data server, I believe.
When you execute:
SELECT DATE(attend_date) ...
the server will return that value as a 4-byte integer representing the number of days since 1899-12-31 (so 1900-01-01 was day 1), which is the internal representation of a DATE in Informix.
Something in a higher layer is then treating it as a 'date + time' value and assuming midnight is the time since there was no time component in the date, and is then rubbing salt in the wound by formatting it in am/pm notation.
This will involve client-side tracing of what's going on. My suspicion (not founded on anything except limited knowledge of the ODBC drivers) is that the problem is occurring in the .NET layers rather than the ODBC driver. However, you're way outside my area of expertise once you're above the ODBC layer (and I don't claim great expertise in ODBC).
You may be able to isolate the problem to the client code by using SQLIDEBUG=2:xyz in the environment (you might need to set that with SETNET32 for Windows). If it works at all on Windows (it does on Unix), then you'll end up with a file with a name starting xyz_ followed by various groups of digits and letters. That file can be analyzed by sqliprint and will show you what was sent to the Informix data server and returned to your client. Assuming the SQL was not hacked en route to the server, then you'll see the date returned as a simple date, and the problem is definitively client-side. If the SQL is hacked en route, then that too is a client-side problem.
It at least gives a starting point for debugging.
Look very carefully at the data types of the types your code is using. In particular, some DBMS have a DATE type that includes time information, and you may need to avoid that interpretation. The SQL standard has DATE (no time), TIME (no date) and TIMESTAMP (date and time) types.

creating a sufficient query search sql

I am writing a query to allow a user to search on what they provide keywords in asp.net, C# and mssql:
string projectPart = null;
string categoryPart = null;
string descriptionPart = null;
if (this.Textbox_ProjectNr.Text.Trim().Length > 0)
projectPart = " AND Number='" + this.Textbox_ProjectNr.Text.Trim() + "' ";
if (this.Textbox_Category.Text.Trim().Length > 0)
categoryPart = " AND Category LIKE '%" + this.Textbox_Category.Text.Trim() + "%' ";
if (this.Textbox_pDescription.Text.Trim().Length > 0)
descriptionPart = " AND ProductDescription LIKE '%" + this.Textbox_pDescription.Text.Trim() + "%' ";
string query = "SELECT * from Project = p.ID " + projectPart + descriptionPart + categoryPart;
I dont know whether this query is sufficient for a traditional query search. Because I see there are some bottlenecks of this search:
if the user does not type anything, it returns all of the data => For this I only do the query when one of the fields are filled.
if the user provides some keywords "P" for each field, the result will be millions of data.
I dont know how to improve the search query basically. any suggestions are appreciated.
Thanks in adavance.
The most important improvement is to protect you code against SQL injection attacks.
You should not concatenate the raw input in the SQL string. If someone searches for the following text for example:
Bwah ha ha'; DROP DATABASE northwind; PRINT'
This will be added to your query to produce
SELECT *
FROM mytable
WHERE category LIKE '%Bwah ha ha'; DROP DATABASE northwind; PRINT'%'
This is a valid SQL command and will happily execute and drop your database (or do anything else the attacker wants)
For more information see SQL Injection and Santitizng Inputs.
You must make this query injection proof! Do not concatenate user entered values, but use parameters, like this:
SqlCommand cmd = new SqlCommand(#"
SELECT * from Project
WHERE
( Number = #Number OR #Number IS NULL ) AND
( Category LIKE #Category OR #Category IS NULL ) AND
( ProductDescription LIKE #ProductDescription OR #ProductDescription IS NULL )", conn);
if(!String.IsNullOrEmpty(this.Textbox_ProjectNr.Text.Trim()))
cmd.Parameters.AddWithValue("#Number", this.Textbox_ProjectNr.Text.Trim());
if(!String.IsNullOrEmpty(this.Textbox_Category.Text.Trim()))
cmd.Parameters.AddWithValue("#Category", this.Textbox_Category.Text.Trim());
if(!String.IsNullOrEmpty(this.Textbox_pDescription.Text.Trim()))
cmd.Parameters.AddWithValue("#ProductDescription", this.Textbox_pDescription.Text.Trim());
Also, you can add some client validation on user entered values. For instance, ask for more than three (?) characaters before running that query.
<asp:TextBox ID="Textbox_ProjectNr" runat="server" />
<asp:RegularExpressionValidator ID="Textbox_ProjectNr_Validator" runat="server"
ControlToValidate="Textbox_ProjectNr"
ErrorMessage="Minimum length is 3"
ValidationExpression=".{3,}" />
First of all, you must protect yourself from sql injections. You haven't specified what connection to the database you are using but most libraries allow adding the parameters in a different field, so they are sanitized automatically.
Secondly, you can (and should) limit the results count using the "LIMIT" (for mysql) or "TOP X" Like so:
Select * from TableName LIMIT 100 or Select TOP 100 * from TableName

Resources