I have a form and I want to send the data to a database. How can I pass the request data through the method parameters and send it to the Database?
int status = InsertCustomer(fName, mName, lName , iage, issn, city, state, country);
//Method
// This method should return an int that the executeUpdate // methods returns. Note: the driver name and the URL are // already available in the init() method.
private int InsertCustomer(String firstName, String midName, String lastName, int age, int ssn, String city, String state, String country) {
// JDBC logic
try {
Class.forName(driverName);
Connection conn = DriverManager.getConnection(databaseURL);
java.sql.Statement st = conn.createStatement();
st.executeUpdate("INSERT INTO Customer(firstName, midName, lastName, age, ssn, city, state, country)" +
"VALUES ('?', '?', '?', ?, ?, '?', '?', '?')";
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return 1;
}
I'm a lil bit lost, a little would be very much appreciated.
Either you use a simple (i.e. not prepared statement), and you can't pass any parameter:
String sql = "insert into sometable (a, b, c) values (7, 8, 9)";
Statement st = conn.createStatement();
return st.executeUpdate(sql);
Or (and in your case, that's what you should do), you use a prepared statament and pass parameters:
String sql = "insert into sometable (a, b, c) values (?, ?, ?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setInt(1, 7);
st.setInt(2, 8);
st.setInt(3, 9);
return st.executeUpdate();
In your code, you're using a simple statement and try to execute a SQL query which needs parameters. That's not possible. You need a prepared statement to do that.
More information in the JDBC tutorial.
Related
I have a method that does two things in one transaction:
1- Changes the state of the clan_gold column in the clan table. It depends on which of the clans won.
2- Saves the Event object to the events table. When saving an Event, among other things, the state of clan_gold of the current clan is fixed before and after the changes.
public class ActionRepository {
private final Connection connection = ConnectionManager.open();
{
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void actionWithEnemy(int bet, Long enemyClanId, Event event) {
try (PreparedStatement preparedStatement =
connection.prepareStatement("BEGIN;"
+ "UPDATE clans SET clan_gold=(SELECT clan_gold FROM clans WHERE clan_id=?) + ? WHERE clan_id=?;"
+ "UPDATE clans SET clan_gold=(SELECT clan_gold FROM clans WHERE clan_id=?) - ? WHERE clan_id=?;"
+ "INSERT INTO events (user_name, clan_name, enemy_clan_name, type, success, gold_before, gold_after, date_time)"
+ "VALUES (?, ?, ?, ?, ?, (SELECT clan_gold FROM clans WHERE clan_id=?), (SELECT clan_gold FROM clans WHERE clan_id=?) + ?, current_timestamp);"
+ "COMMIT;")) {
preparedStatement.setLong(1, CurrentUser.getCurrentUser().getClan().getId());
preparedStatement.setInt(2, bet);
preparedStatement.setLong(3, CurrentUser.getCurrentUser().getClan().getId());
preparedStatement.setLong(4, enemyClanId);
preparedStatement.setInt(5, bet);
preparedStatement.setLong(6, enemyClanId);
preparedStatement.setString(7, event.getUserName());
preparedStatement.setString(8, event.getClanName());
preparedStatement.setString(9, event.getEnemyClanName());
preparedStatement.setString(10, event.getEventType().toString());
preparedStatement.setBoolean(11, event.isSuccess());
preparedStatement.setLong(12, CurrentUser.getCurrentUser().getClan().getId());
preparedStatement.setLong(13, CurrentUser.getCurrentUser().getClan().getId());
preparedStatement.setInt(14, bet);
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
But the Event object persists unpredictably to me.
I expect the gold_before value of each following line to match the gold_after value of the previous line. But it is not always the case.
It occurs both at start of one flow and .
The total amount of gold of all clans always remains the same, which means there is no data loss.
I am using postgres
I want to check the username and password with sqlite table,In my case query always returns false...
This is my Query...
public boolean validateUser(String u_name, String p_word){
Cursor c = getReadableDatabase().rawQuery(
"SELECT FNAME,PASSWORD FROM " + TABLE_NAME + " WHERE "
+ fname + "='" + u_name+"'AND "+ password +"='"+ p_word+"'" , null);
if (c!=null)
{
return true;
}
else{
return false;
}
}
Checking whether or not the Cursor is null is basically useless as a valid Cursor will be returned by rawQuery. That is no data to extract will result in an empty Cursor with no rows, whilst if data has been extracted the Cursor will have 1 or more rows.
You should check whether or not the Cursor is empty by using the Cursor getCount() method which will return 0 if there are no rows or the number of rows. Alternately you could use some of the Cursor's move methods which will return true/false depending upon whether the move can be performed. e.g if (c.moveToFirst) { ... //row(s) exist} else { ... //no rows exists }.
You should also close the Cursor before returning. So perhaps use :-
public boolean validateUser(String u_name, String p_word){
Cursor c = getReadableDatabase().rawQuery(
"SELECT FNAME,PASSWORD FROM " + TABLE_NAME + " WHERE "
+ fname + "='" + u_name+"'AND "+ password +"='"+ p_word+"'" , null);
int count = c.getCount(); // get the number of rows
c.close(); // Close the Cursor
return count > 0; // return result (no data found = false, else true)
Many would recommend not using rawQuery but rather the convenience Cursor query method. This could be :-
public boolean validateUser(String u_name, String p_word) {
String[] columns = new String[]{
FNAME,
PASSWORD
};
String whereclause = FNAME + "=? AND " + PASSWORD + "=?";
String[] whereargs = new String[]{
u_name,
p_word
};
Cursor c = this.getWritableDatabase().query(
TABLE_NAME,
columns,
whereclause,
whereargs,
null,null,null
);
int count = c.getCount();
c.close();
return count > 0;
}
Note the above code is in-principle code and hasn't been tested so it may contain typing errors.
The above code assumes that the method is within the Database Helper class (i.e. a subclass of SQLiteOpenHelper).
The assumption has been made that FNAME and PASSWORD are the correct String variables to be used for the column names as opposed to fname and password
Assumptions have been made due to the limited code made available.
I have a insert sp
create procedure sp_insert_services
#Service_Type nvarchar(50),
#Frequency nvarchar(50),
as
insert INTO tbl_fl_Master_List
(Service_Type,Frequency)
values
(#Service_Type,
#Frequency)
now how i write this through lambda expression,linq to sql and EF?
i tried this but this show error
var insert = insertt.tbl_fl_Master_List();
if(insertt!=null)
{
insertt.tbl_fl_Master_List.Add();
}
insertt.SaveChanges();
Error 8 Non-invocable member 'chart_project.Track_Data.tbl_fl_Master_List' cannot be used like a method.
Error 9 No overload for method 'Add' takes 0 arguments
and also i try this
public static string Insert_master_services(string Service_Type,string Frequency)
{
Data insertt=new Data();
tbl_fl_Master_List t = new tbl_fl_Master_List();
t.Service_Type = Service_Type;
t.Frequency = Frequency;
insertt.SaveChanges();
}
I am using NpgSQL with PostgreSQL and ADO.NET. Forgive the simplicity of the question as I just started using PostgreSQL and NpgSQL this week.
Something like this works fine:
[Test]
public void InsertNoParameters()
{
NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
conn.Open();
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (FirstName,LastName) VALUES ('Test','Tube')";
command.CommandText = sql;
command.ExecuteNonQuery();
conn.Close();
}
When I put in parameters I get the error message:
Npgsql.NpgsqlException : ERROR: 42703: column "_firstname" does not exist
[Test]
public void InsertWithParameters()
{
NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
conn.Open();
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (FirstName,LastName) VALUES (_FirstName,_LastName)";
command.CommandText = sql;
var parameter = command.CreateParameter();
parameter.ParameterName = "_FirstName";
parameter.Value = "Test";
command.Parameters.Add(parameter);
parameter = command.CreateParameter();
parameter.ParameterName = "_LastName";
parameter.Value = "Tube";
command.Parameters.Add(parameter);
command.ExecuteNonQuery();
conn.Close();
}
The responses in the comments are correct:
Npgsql doesn't support _ as a parameter placeholder notation. You should be using # or : (so #FirstName or :FirstName, not _FirstName).
PostgreSQL will automatically lower-case your table and column names unless they are double-quoted. Either use lower-case names for everything (simpler) or quote identifiers in your SQL queries.
So your code should look more or less like this:
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (first_name, last_name) VALUES (#FirstName,#LastName)";
command.CommandText = sql;
var parameter = command.CreateParameter();
parameter.ParameterName = "FirstName";
parameter.Value = "Test";
command.Parameters.Add(parameter);
I'm attempting to parse SQL using the TSql100Parser provided by microsoft. Right now I'm having a little trouble using it the way it seems to be intended to be used. Also, the lack of documentation doesn't help. (example: http://msdn.microsoft.com/en-us/library/microsoft.data.schema.scriptdom.sql.tsql100parser.aspx )
When I run a simple SELECT statement through the parser it returns a collection of TSqlStatements which contains a SELECT statement.
Trouble is, the TSqlSelect statement doesn't contain attributes such as a WHERE clause, even though the clause is implemented as a class. http://msdn.microsoft.com/en-us/library/microsoft.data.schema.scriptdom.sql.whereclause.aspx
The parser does recognise the WHERE clause as such, looking at the token stream.
So, my question is, am I using the parser correctly? Right now the token stream seems to be the most useful feature of the parser...
My Test project:
public static void Main(string[] args)
{
var parser = new TSql100Parser(false);
IList<ParseError> Errors;
IScriptFragment result = parser.Parse(
new StringReader("Select col from T1 where 1 = 1 group by 1;" +
"select col2 from T2;" +
"select col1 from tbl1 where id in (select id from tbl);"),
out Errors);
var Script = result as TSqlScript;
foreach (var ts in Script.Batches)
{
Console.WriteLine("new batch");
foreach (var st in ts.Statements)
{
IterateStatement(st);
}
}
}
static void IterateStatement(TSqlStatement statement)
{
Console.WriteLine("New Statement");
if (statement is SelectStatement)
{
PrintStatement(sstmnt);
}
}
Yes, you are using the parser correctly.
As Damien_The_Unbeliever points out, within the SelectStatement there is a QueryExpression property which will be a QuerySpecification object for your third select statement (with the WHERE clause).
This represents the 'real' SELECT bit of the query (whereas the outer SelectStatement object you are looking at has just got the 'WITH' clause (for CTEs), 'FOR' clause (for XML), 'ORDER BY' and other bits)
The QuerySpecification object is the object with the FromClauses, WhereClause, GroupByClause etc.
So you can get to your WHERE Clause by using:
((QuerySpecification)((SelectStatement)statement).QueryExpression).WhereClause
which has a SearchCondition property etc. etc.
Quick glance around would indicate that it contains a QueryExpression, which could be a QuerySpecification, which does have the Where clause attached to it.
if someone lands here and wants to know how to get the whole elements of a select statement the following code explain that:
QuerySpecification spec = (QuerySpecification)(((SelectStatement)st).QueryExpression);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Select Elements");
foreach (var elm in spec.SelectElements)
sb.Append(((Identifier)((Column)((SelectColumn)elm).Expression).Identifiers[0]).Value);
sb.AppendLine();
sb.AppendLine("From Elements");
foreach (var elm in spec.FromClauses)
sb.Append(((SchemaObjectTableSource)elm).SchemaObject.BaseIdentifier.Value);
sb.AppendLine();
sb.AppendLine("Where Elements");
BinaryExpression binaryexp = (BinaryExpression)spec.WhereClause.SearchCondition;
sb.Append("operator is " + binaryexp.BinaryExpressionType);
if (binaryexp.FirstExpression is Column)
sb.Append(" First exp is " + ((Identifier)((Column)binaryexp.FirstExpression).Identifiers[0]).Value);
if (binaryexp.SecondExpression is Literal)
sb.Append(" Second exp is " + ((Literal)binaryexp.SecondExpression).Value);
I had to split a SELECT statement into pieces. My goal was to COUNT how many record a query will return. My first solution was to build a sub query such as
SELECT COUNT(*) FROM (select id, name from T where cat='A' order by id) as QUERY
The problem was that in this case the order clause raises the error "The ORDER BY clause is not valid in views, inline functions, derived tables, sub-queries, and common table expressions, unless TOP or FOR XML is also specified"
So I built a parser that split a SELECT statment into fragments using the TSql100Parser class.
using Microsoft.Data.Schema.ScriptDom.Sql;
using Microsoft.Data.Schema.ScriptDom;
using System.IO;
...
public class SelectParser
{
public string Parse(string sqlSelect, out string fields, out string from, out string groupby, out string where, out string having, out string orderby)
{
TSql100Parser parser = new TSql100Parser(false);
TextReader rd = new StringReader(sqlSelect);
IList<ParseError> errors;
var fragments = parser.Parse(rd, out errors);
fields = string.Empty;
from = string.Empty;
groupby = string.Empty;
where = string.Empty;
orderby = string.Empty;
having = string.Empty;
if (errors.Count > 0)
{
var retMessage = string.Empty;
foreach (var error in errors)
{
retMessage += error.Identifier + " - " + error.Message + " - position: " + error.Offset + "; ";
}
return retMessage;
}
try
{
// Extract the query assuming it is a SelectStatement
var query = ((fragments as TSqlScript).Batches[0].Statements[0] as SelectStatement).QueryExpression;
// Constructs the From clause with the optional joins
from = (query as QuerySpecification).FromClauses[0].GetString();
// Extract the where clause
where = (query as QuerySpecification).WhereClause.GetString();
// Get the field list
var fieldList = new List<string>();
foreach (var f in (query as QuerySpecification).SelectElements)
fieldList.Add((f as SelectColumn).GetString());
fields = string.Join(", ", fieldList.ToArray());
// Get The group by clause
groupby = (query as QuerySpecification).GroupByClause.GetString();
// Get the having clause of the query
having = (query as QuerySpecification).HavingClause.GetString();
// Get the order by clause
orderby = ((fragments as TSqlScript).Batches[0].Statements[0] as SelectStatement).OrderByClause.GetString();
}
catch (Exception ex)
{
return ex.ToString();
}
return string.Empty;
}
}
public static class Extension
{
/// <summary>
/// Get a string representing the SQL source fragment
/// </summary>
/// <param name="statement">The SQL Statement to get the string from, can be any derived class</param>
/// <returns>The SQL that represents the object</returns>
public static string GetString(this TSqlFragment statement)
{
string s = string.Empty;
if (statement == null) return string.Empty;
for (int i = statement.FirstTokenIndex; i <= statement.LastTokenIndex; i++)
{
s += statement.ScriptTokenStream[i].Text;
}
return s;
}
}
And to use this class simply:
string fields, from, groupby, where, having, orderby;
SelectParser selectParser = new SelectParser();
var retMessage = selectParser.Parse("SELECT * FROM T where cat='A' Order by Id desc",
out fields, out from, out groupby, out where, out having, out orderby);