Performing Increment and Decrement with PreparedStatement [duplicate] - java

This question already has answers here:
how to increment integer Columns value by 1 in SQL
(8 answers)
Closed 7 years ago.
I have a column in my database which just contains a counter value. The value should be 1 if the entry is new, otherwise it will either be incremented or decremented if the entry is being updated.
I am trying to figure out how to use the java.sql.PreparedStatement for this purpose.
It is to my understanding that the SQL query which eventually has to be created has to look like:
INSERT INTO `DropletNames` (`Title`,`Count`) VALUES ('Travel to Mars',Count + 1)
My question is: how do I create this query? (fyi: I know the Count + 1 is sort of irrelevant here, since INSERT should always set it to 1, but I am trying to use the same syntax for INSERT as I would for UPDATE)
I tried doing the following:
String query = "INSERT INTO `DropletNames` (`Title`,`Count`) VALUES (?,?)";
PreparedStatement stm = con.prepareStatement(query);
stm.setString(1,"Travel to Mars");
stm.setString(2,"Count + 1"); // I used this because I couldn't find a better way of setting this
However, that obvious produces the wrong result, because it attempts to insert "Count + 1" as a String, instead of evaluating Count + 1.
The only other way I can think of doing it is:
String query = "INSERT INTO `DropletNames` (`Title`,`Count`) VALUES (?,Count + 1)";
PreparedStatement stm = con.prepareStatement(query);
stm.setString(1,"Travel to Mars");
But I am unsure if that violates the "best practices" rules for using the PreparedStatement's setter methods when building the SQL Statement. I cannot see how that would leave me open to SQL injection or other vulnerabilities, but maybe there is something I haven't considered.
Is there a way to do this using the PreparedStatement class, or is my second solution the way I should do this?

If you want to increment a column value then the syntax is
UPDATE `DropletNames` SET `Monday` = `Monday` + 1 WHERE `Title = "Travel to Mars"
That will just add 1 to whatever value is in the Monday column. Similarly if you want to decrement the value it will be
UPDATE `DropletNames` SET `Monday` = `Monday` - 1 WHERE `Title = "Travel to Mars"
Now the only thing you need to change to make this into a prepared statement is the placeholder for the WHERE value.

After reading your comments, you appear to want to increment a value that counts a value per day. Try the following example:
--Create Schema
CREATE TABLE #day(
[ID] int,
[DayOfWeek] NVARCHAR(16),
[Value] INT
)
--Add Days
INSERT INTO #day ([ID], [DayOfWeek], [Value]) VALUES
(1,'Sunday',0),
(2,'Monday',0),
(3,'Tuesday',0),
(4,'Wednesday',0),
(5,'Thursday',0),
(6,'Friday',0),
(7,'Saturday',0)
--Increment Day Example
UPDATE #day
SET [Value] += 1
WHERE [DayOfWeek] = 'Sunday'
--Increment Day Based on the current day
UPDATE #day
SET [Value] += 1
WHERE [ID] = DAY(GETDATE())
--Display Table
SELECT * FROM #day
OUTPUT:
ID DayOfWeek Value
1 Sunday 1
2 Monday 1
3 Tuesday 0
4 Wednesday 0
5 Thursday 0
6 Friday 0
7 Saturday 0

Related

How to print a single statement as a whole statement in java without splitting it because of having multiple user values inside it?

i m trying to execute a sql command in java where values are taken within the statement from user .For example- update stock set name= + value 1+ quantity = value 2 + where stock_id=?'
here value 1 and value 2 are taken from user and herei want to execute the whole statement as a single command without splitting it which causes the change in meaning of Update command in sql
Do you want something like this?
PreparedStatement stmt = Connection
.prepareStatement("UPDATE stock SET name = ?, quantity = ? WHERE stock_id=?");
stmt.setString(1,value1); //1 specifies the first parameter(?) in the query
stmt.setInt(2,value2); //2
stmt.setInt(3, stock_id) //3

Getting the totalworkingdays dates through passing the dates dynamically

This is my MySQL database table structure and attendancedate datatype is Date:
attendancedate-------admissionnumber------------attendance
2013-10-03-----------LSTM-0008/2013-2014--------present
2013-10-09-----------LSTM-0008/2013-2014--------present
2013-11-02-----------LSTM-0008/2013-2014--------absent
and i want to disaply like that
monthname---------totalworkingdays---------present----absent
october-------------- 2--------------------2----------0
November--------------1--------------------0-----------1
so am writing the below MySQL query:
select monthname(attendencedate) as monthname,
(select distinct count(*)
from lstms_attendence
where attendencedate>='2013-10-03'
and attendencedate<='2013-10-09'
and addmissionno='LSTM-0008/2013-2014')as totalworkingdays,
sum(CASE WHEN attendence = 'present' THEN 1 ELSE 0 END) as present,
SUM(CASE WHEN attendence = 'absent' THEN 1 ELSE 0 END) AS absent
FROM lstms_attendence
WHERE addmissionno='LSTM-0008/2013-2014' GROUP BY monthname(attendencedate);
But the query is display like this:
monthname---------totalworkingdays---------present----absent
November-----------3-----------------------0------------2
October------------3-----------------------2------------1
please give me the exact query and here am passing dates as hardcoded but that dates are passing dynamically through java to that query.
Let me know the how to create dynamically dates and how to pass values to that query.
Try this:
SELECT
MONTHNAME(attendencedate) as the_month,
COUNT(*) as working_days,
SUM(IF(attendance='present',1,0)) as is_present,
SUM(IF(attendance='absent',1,0)) as is_absent
FROM
lstms_attendence
WHERE
addmissionno='LSTM-0008/2013-2014'
GROUP BY
the_month
Your question doesn't make clear what you're asking. What's wrong with your resultset? Is it the presence of your "november" row?
At any rate, you've got an excessively complex query here, as well as one which will break if you happen to include data from multiple years in it.
Instead of using MONTHNAME(attendancedate), we'll use
DATE_FORMAT(attendancedate, '%Y-%c-01') AS attendancemonth
to figure out in which month an attendancedate lies. This simply turns '2013-11-15' into '2013-11-01', the first day of the month in question. In other words, it truncates (rounds down) the date to the first day of the month.
SELECT admissionnumber,
DATE_FORMAT(attendancedate, '%Y-%c-01') AS attendancemonth,
COUNT(*) AS working_days,
SUM(IF(attendance='present',1,0)) AS is_present,
SUM(IF(attendance='absent',1,0)) AS is_absent
FROM lstms_attendence
WHERE attendancedate >= '2013-10-03'
AND attendancedate < '2013-10-06' + INTERVAL 1 DAY
AND admissionnumber='LSTM-0008/2013-2014'
GROUP BY admissionnumber,attendancemonth
Here is a sqlfiddle.http://sqlfiddle.com/#!2/a2dfb/7/0
This summarizes by both admissionnumber and month, so you can produce a report that contains multiple admissions if you want that.
It uses attendancedate < 'last' + INTERVAL 1 DAY in place of attendancedate <= 'last' because that is robust in cases where attendancedate contains a timestamp other than midnight.
If you need to pass in your parameters from Java, use a prepared statement. Replace the constants in the SQL query with ?, and use setTimestamp and setString. For one example, see JDBC Prepared Statement . setDate(....) doesn't save the time, just the date.. How can I save the time as well?

Java MySql preparedStatement

Hey I have problem with preparedStatement, I want to find min for few columns, I'm iterating over the names of columns and inserting them inside my preparedStatement like that
connection.prepareStatement("SELECT min( ? ) as min FROM test");
minStatement.setString(1, "some_column");
and when retrieving from ResultSet I'm getting the column name, in this case the result is "some_column" and should be 0. When using normal statement it does return right value.
I have no idea what I'm doing wrong.
Thanks for any help.
You cannot specify a column name in prepared statement like this, what you get is:
SELECT MIN('some_column') AS min FROM test
Instead of:
SELECT MIN(some_column) AS min FROM test
So, your query selects the minimal value 'some_column'... which is 'some_column'.
You could, instead, try that:
connection.prepareStatement("SELECT min(" + some_column + " ) as min FROM test");
But this may lead to injection attacks.

Auto Increment including Year and Month in MySql

I have a table called > Project with an auto increment field for project estimate bid number called Project_ID.
This field is auto incremented. I have created it as an 8 digit character field which carries the field rule.
I need it to auto increment as a two number year, two number month, include a hyphen, and then a number starting at 001 for first record in that time period.
An example for the month of April 2012 would be 1204-001 for the first
record, 1204-002 for the 2nd and etc. then when the month of May rolls
around the Project_ID would change to 1205-001.
What I’ve been trying to write is as follows, I kept it as a simple default expression with a default value of
Cyear(date()) + (month()) + “-“ + “001” .
How I have Achieve this?
Basically, you can use BEFORE INSERT TRIGGER on the table you want the column to be incremented.
Here are some steps to create a simple algorithm and put this code inside the trigger:
// get current YEAR
SET #cur_Year = CONCAT(DATE_FORMAT(CURDATE(), '%Y'));
// get current MONTH
SET #cur_MONTH = CONCAT(DATE_FORMAT(CURDATE(), '%m'));
// concatenate YEAR and MONTH
SET #Year_Month = CONCAT(#cur_Year, #cur_MONTH);
// get the last value for the current YEAR and MONTH
SET #max_ID = ( SELECT MAX(ID)
FROM tableName
WHERE ID LIKE CONCAT(#Year_Month, '-%'));
// get the last three characters from the id, convert in to
// integer and increment by 1
SET #last_ID = CAST(RIGHT(#max_ID, 3) AS SIGNED) + 1;
// pad zero on the left using LPAD and
// concatenate it with YEAR and MONTH
SET #new_ID = CONCAT(#Year_Month,'-',LPAD(CAST(#last_ID AS CHAR(3)), 3, '0'));
INSERT INTO (Project_ID, col1, col2, col3)
SELECT DATE_FORMAT(NOW(), CONCAT('%y%m-',
(( SELECT RIGHT(CONCAT('000', (RIGHT(Project_ID, 3) + 1)), 3) AS number
FROM table_name
WHERE LEFT(Project_ID, 5) = DATE_FORMAT(NOW(), '%y%m-'))
ORDER BY Project_ID DESC
UNION
( SELECT '001')
LIMIT 1))),
'Col1 data', 'Col2 data', 'Col3 data'
This might look a bit odd, so I'll just explain the flow:
I use INSERT INTO ... SELECT so that I can check existing data from table_name to see if there are any existing cases already. The WHERE will find existing cases, and thanks to both RIGHT and LEFT it isn't too hard to carve out relevant data needed. If no rows are found, '001' is used instead, then you simply assign the existing columns as shown.
I have absolutely solved it,just take a look..
At first you have to take a sample table where the columns will be same to the columns of your original table except the column project_id.
then first insert a row in the original table where the value of column project_id=0 and the other columns are null,just insert the first row manually like this.
Then create a trigger on the sample table like the following...
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
delimiter ;;
create trigger t after insert on try
for each row
begin
declare v int;
declare c int;
set v=(select max(project_id) from original);
if(v=0)then
insert into original set
project_id=concat((select concat(right(substring_index((select * from(select curdate() from try limit 1) as a),'-','1'),2),right(substring_index((select * from(select curdate() from try limit 1) as a),'-','2'),2)) from try limit 1),'-001'),
project=new.project;
else
set c=(select right((select max(project_id) from original)as x,3) from original limit 1);
insert into original set
project_id=concat((select concat(right(substring_index((select * from(select curdate() from try limit 1) as a),'-','1'),2),right(substring_index((select * from(select curdate() from try limit 1) as a),'-','2'),2)) from try limit 1),concat('-00',c+1)),
project=new.project;
delete from original limit 1;
end if;
end;;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
In the above trigger my sample table was try(project text) and the original table was original(project_id text,project text).
After creating a trigger like this on the sample table,start inserting rows in the sample table,the rows will automatically inserted in the original table with auto_increment values in the project_id column like..1405-001,1405-002,1405-003.... where 14 is 2014 and 05 is May and the rest are auto_incremented values which is being incremented using the trigger.
Just follow the above steps, your problem will be surely solved.

Inserting values in to oracle table using jsp

I am using the following code to insert values in to a table.
String sql = "INSERT INTO APPLICATION VALUES (?,?,?,?,?,?,TO_DATE(?,'DD/MMYYYY'),?,TO_DATE(?,'DD/MM/YYYY'),?,?,?,?,?,SYSDATE,'X',?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,Integer.parseInt(sr));
pstmt.setString(2,nm);
pstmt.setString(3,(String)session.getValue("ITSGTYP"));
pstmt.setString(4,pst);
pstmt.setString(5,dox);
pstmt.setString(6,zo);
pstmt.setString(7,dob);
pstmt.setString(8,cdr);
pstmt.setString(9,cdrdt);
pstmt.setString(10,qual);
pstmt.setString(11,mail);
pstmt.setString(12,bond);
pstmt.setInt(13,Integer.parseInt((String)session.getValue("USER")));
pstmt.setString(14,request.getRemoteAddr());
pstmt.setString(17,place);
The description of the table into which the values are inserted is as follows
EMP_ID NOT NULL NUMBER(6)
NAME VARCHAR2(25)
APPLN_TYP VARCHAR2(10)
POST VARCHAR2(100)
DIV VARCHAR2(25)
ZONE VARCHAR2(5)
DOB DATE
CADRE VARCHAR2(5)
CADRE_DATE DATE
QUALIFICATION VARCHAR2(100)
EMAIL_ID VARCHAR2(70)
BOND VARCHAR2(3)
SUBMITTED_BY NUMBER(6)
SUBMIT_IP VARCHAR2(30)
SUBMIT_DATE DATE
FLAG VARCHAR2(1)
PLACE VARCHAR2(20)
While executing the above code I am getting the following error
Error: java.sql.SQLException: Invalid column index
This query was working fine before.
My previous table didn't have the PLACE column. I had to insert it at a later point.
It's safer to include the columns names you want to insert into the SQL statement like:
String sql = "INSERT INTO APPLICATION VALUES (EMP_ID,NAME, ....) // etc
(?,?,?,?,?,?,TO_DATE(?,'DD/MMYYYY'),?,TO_DATE(?,'DD/MM/YYYY'),?,?,?,?,?,SYSDATE,'X',?)";
In this way, you have more control of the indexes and the columns you are using in your statement.
Replace pstmt.setString(17,place);
with
pstmt.setString(15,place);
The reason for error you get is :
You don't have 17 ? symbols in your query for prepared statement, you only have 15 ? symbols that means you can only set 15 values (for 15 columns) for that prepared statement.
Now what you were doing is you were setting a parameter at 17 th index and you don't have any column specified at index 17 in your query, you only have 15 columns and 15 ? symbols for the values to be inserted at respective 15 columns.
So replace it with what I mentioned above and it will work.
In your query u have 15 parameters to set. And you are trying to give value of 17th index. You should change it to 15 instead of 17.
i.e
pstmt.setString(15,place);

Categories