SQL Server: How to get "OUTPUT" from Insert on JAVA? - java

For some reason, I'm trying to get data from the field that I just inserted. And to be clear: Nope, I'm not seeking a way to get "Insert ID".
For example, I have a table named "Members", and I do inserts like this:
INSERT INTO Members (ID, NAME, PHONE, BIRTH, CREATE_DATE) OUTPUT Members.CREATE_DATE VALUES (NEXT VALUE FOR SeqID, ?, ?, ?, getdate());
This SQL works good and give me the CREATE_DATE that I want in SQL Management.
But my question is: How to get THAT CREATE_DATE using JAVA's prepared-statement?
I tried to get that using ResultSet, and it told me "Statement didn't return the ResultSet"
con = ds.getConnection();
pstmt = con.prepareCall(INSERT);
pstmt.setString(1, name);
pstmt.setString(2, phone);
pstmt.setString(3, birth);
ResultSet rs = pstmt.executeQuery();
if(rs.next()) System.out.println(rs.getString("CREATE_DATE"));
And registeroutparameter don't look right too because it is "CREATE_DATE", not a "?". Is there any way that I could get my data from OUTPUT?

It is not :
pstmt = con.prepareCall(INSERT);
You have to use prepareStatement:
pstmt = con.prepareStatement(INSERT);
Also : Insert is not Select, instead of pstmt.executeQuery(); it should pstmt.executeUpdate(); which return an int and not a ResultSet, so if you want to check if your query success or not you have to use :
int s = pstmt.executeUpdate();
if(s > 0){
//success
}
But my question is: How to get THAT CREATE_DATE using JAVA's
prepared-statement?
You have to use two separate statement one for insert and the second for select

The prepared statement is compiled server side and the parameters are provided by the client the getdate function is executed server side and not returned to the client.
To get the date client side there are many options :
write a procedure with output parameters which insert the row and return the date
compute date client side and send to server
request the server with select query, but this needs two calls

Related

why does my sql table treat 1000 as a middle number?

When I try to sort by a value descending my SQL table does it correctly, but if it sees for example "1000" it always puts it in the middle?
for Example:
this even happens when I reference it in spigot (I'm using it for a plugin) it outputs it the same way
this is how I'm calling it in my plugin:
PreparedStatement statement = database.getConnection().prepareStatement("SELECT uuid FROM player_stats ORDER BY blocks_broken DESC");
ResultSet rs = statement.executeQuery();
while (rs.next()) {
String name = rs.getString("uuid");
LeaderboardCommand.name = name;
String player = String.valueOf(Bukkit.getPlayer(UUID.fromString(name)));
p.sendMessage(player);
I know it's not perfect as I'm just learning/experimenting with databases currently, but I'm mainly asking for help on why the SQL is outputted this way & advice on any severe mistakes I'm making is greatly appreciated!
Thanks in advance -Occy
public void createPlayerStats(PlayerStats playerStats) throws SQLException {
PreparedStatement statement = getConnection()
.prepareStatement("INSERT INTO player_stats(uuid, blocks_broken, last_login, last_logout) VALUES (?, ?, ?, ?)");
statement.setString(1, playerStats.getPlayerUUID());
statement.setLong(2, playerStats.getBlocksBroken());
statement.setDate(3, new Date(playerStats.getLastLogin().getTime()));
statement.setDate(4, new Date(playerStats.getLastLogout().getTime()));
statement.executeUpdate();
statement.close();
It happens because block_broken type is a varchar and not a number.
In this case you are ordering lexycographically and not numerically.
You can change your query to handle that as a numeric value with an explicit cast so your query should be:
SELECT uuid FROM player_stats ORDER BY cast(blocks_broken as numeric) DESC
Update: In MariaDb try to use this (You can try directly in the db client and once it is working update your java code):
SELECT uuid FROM player_stats ORDER BY CAST(blocks_broken AS INTEGER) DESC

How to insert a row into database?

I have written this code to add stuff to the database, however, when I try running it it does not work, i've been looking for ways to do it, but i just cant seem to find the solution, can anyone help?
String mySQL ="INSERT INTO Measurement (Level, Time, Date, TankID)"+"VALUES (textField1, currentTime,currentDate,(SELECT TankID FROM Tanks WHERE TankName = '2' AND Site_ID = '1'))";
stmt.executeUpdate(mySQL);
Both your SQL and prepared statement are malformed. Try using an INSERT INTO ... SELECT here:
String sql = "INSERT INTO Measurement (Level, Time, Date, TankID) ";
sql += "SELECT ?, ?, ?, TankID ";
sql += "FROM Tanks ";
sql += "WHERE TankName = '2' AND Site_ID = '1'";
stmt.setString(1, textField1);
stmt.setString(2, currentTime); // not sure about the type here
stmt.setString(3, currentDate); // also not sure about the type
stmt.executeUpdate();
Note that I am unsure about both the Java and SQL binding types of the columns for currentTime and currentDate. If not string, then the above would have to change slightly.
You should be using PreparedStatement to properly set the first parameter of the insert query and check the documentation of your DB server to use existing functions to get current time and date.
For example, mySQL has functions CURDATE() and CURTIME()
String query = "INSERT INTO Measurement (Level, Time, Date, TankID) "
+ "VALUES (?, CURTIME(), CURDATE(), (SELECT TankID FROM Tanks WHERE TankName = '2' AND Site_ID = '1'))";
try (PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, textField1); // could be textField1.getText() or textField1.getValue()
statement.executeUpdate();
}
Based on your Database type change the connection details
Follow this Link for creating JDBC Connection and Inserting data
If you did the above steps please ignore this..

getting the result of sql command in java [duplicate]

This question already has an answer here:
java.sql.sqlexception column not found
(1 answer)
Closed 4 years ago.
i need to get the last id entered in my data base witch is AUTO_INCREMENT so i did this
String Var = "SELECT MAX(id) FROM goupe ; ";
ResultSet vari=st.executeQuery(Var);
while(vari.next()){
nombre = vari.getInt("id");}
String sql = "INSERT INTO Student(name,famillyname,email,password,module,speciality,card,id_goupe)VALUES('"+name+"','"+familly+"','"+email+"','"+pass+"','"+module+"','"+specialite+"','"+card+"','"+nombre+"');";
st.execute(sql);
but i had this problem Column 'id' not found.
so what should i do to have it right .
I have to say, there are a couple of really easy things you can do to greatly improve your code.
If your latest ID is generated elsewhere, then embed the query directly into the statement such that you don't need to go get it. That will reduce the risk of a race condition.
Use PreparedStatements. Let me ask you this question: What do you suppose is going to happen if one of your user's name is O'Ryan?
Since your code is just a snip, I also will only provide a snip:
int index = 1;
String sql = "INSERT INTO Student(name,famillyname,email,password,module,speciality,card,id_goupe)" +
"VALUES(?,?,?,?,?,?,?,(SELECT MAX(id) FROM goupe));";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(index++, name);
ps.setString(index++, familyname);
ps.setString(index++, email);
ps.setString(index++, password);
ps.setString(index++, module);
ps.setString(index++, speciality);
ps.setString(index++, card);
int rows = ps.executeUpdate();
if(rows == 1) {
System.out.println("Successfully inserted row");
}
When you execute the query SELECT MAX(id) FROM goupe;, then in the returned table, the column name no longer remains as id.
So, the best approach is to provide a name for the column like below:
SELECT MAX(id) AS maxid FROM goupe;
Then, you can get the value using:
vari.getInt("maxid")

SQLServer Exception: Invalid column name

com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name 'IDPaciente'
I am getting this exception. This is my code:
String query = "INSERT INTO Paciente('IDPaciente', 'NomePaciente', 'IdadePaciente', 'LocalidadePaciente') VALUES('"+IDTextField.getText()+"', '"+NomeTextField.getText()+"', '"+IdadeTextField.getText()+"', '"+LocalidadeTextField.getText()+"')";
try
{
st = con.DatabaseConnection().createStatement();
rs = st.executeQuery(query);
}
I suspect the problem might be in the query itself.
I have searched a lot and couldn't find the solution to my problem. I have tried refreshing the cache, changing permissions within the schema, restarting sql server (I am using sql server management studio 2012), I am correctly connected to my database, and nothing seems to work.
What could I be doing wrong?
Thank you!
Remove quotes , try :
String query = "INSERT INTO Paciente(IDPaciente, NomePaciente, IdadePaciente, LocalidadePaciente) VALUES('"+IDTextField.getText()+"', '"+NomeTextField.getText()+"', '"+IdadeTextField.getText()+"', '"+LocalidadeTextField.getText()+"')";
try
{
st = con.DatabaseConnection().createStatement();
rs = st.executeQuery(query);
}
Remove also quotes for INT values.
Your code is not secure, you can easily get Syntax error or SQL Injection I suggest to use PreparedStatement instead.
You have a problem in your Query, the columns should not be between '' so you can use this instead :
String query = "INSERT INTO Paciente(IDPaciente, NomePaciente, IdadePaciente, "
+ "LocalidadePaciente) VALUES(?, ?, ?, ?)";
try (PreparedStatement insert = con.prepareStatement(query)) {
insert.setString(1, IDTextField.getText());
insert.setString(2, NomeTextField.getText());
insert.setString(3, IdadeTextField.getText());
insert.setString(4, LocalidadeTextField.getText());
insert.executeUpdate();
}
If one of your column is an int you have to use setInt, if date setDate, and so on.
You have four problems, though only the first is giving you the current error:
Single-quotes (') are for quoting text literals, not column names. In MS SQL Server, you can quote column names using double-quotes (") or square brackets ([]), but you don't need to quote them at all.
To prevent SQL Injection attacks, where hackers will steal your data and delete your tables, and to prevent potential syntax errors, never build a SQL statement with user-entered strings, using string concatenation. Always use a PreparedStatement.
Always clean up your resources, preferably using try-with-resources.
Don't use executeQuery() for an INSERT statement. Use executeUpdate(). As the javadoc says:
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, such as a DDL statement.
So, your code should be:
String query = "INSERT INTO Paciente" +
" (IDPaciente, NomePaciente, IdadePaciente, LocalidadePaciente)" +
" VALUES (?, ?, ?, ?)";
try (PreparedStatement st = con.DatabaseConnection().prepareStatement(query)) {
st.setString(1, IDTextField.getText());
st.setString(2, NomeTextField.getText());
st.setString(3, IdadeTextField.getText());
st.setString(4, LocalidadeTextField.getText());
st.executeUpdate();
}
Remove the quotes from your column names.
"INSERT INTO Paciente(IDPaciente, NomePaciente, IdadePaciente, LocalidadePaciente) VALUES('"+IDTextField.getText()+"', '"+NomeTextField.getText()+"', '"+IdadeTextField.getText()+"', '"+LocalidadeTextField.getText()+"')"
The Column names are does not typed within quotes, Remove them and try again.
Demo:-
Create table MyTable (id int , name varchar (50))
go
insert into MyTable (id,name) values (1 , 'ahmed')
Result:-
(1 row(s) affected)
Try insert them again with quotes.
insert into MyTable ('id','name') values (1 , 'ahmed')
Result:-
Msg 207, Level 16, State 1, Line 3
Invalid column name 'id'.
Msg 207, Level 16, State 1, Line 3
Invalid column name 'name'.

Value from last inserted row in DB [duplicate]

This question already has answers here:
How to get a value from the last inserted row? [duplicate]
(14 answers)
Closed 9 years ago.
Is there some way to get a value from the last inserted row?
I am inserting a row where the PK will automatically increase due to sequence created, and I would like to get this sequence number. Only the PK is guaranteed to be unique in the table.
I am using Java with a JDBC and Oracle.
I forgot to add that I would like to retrieve this value using the resultset below. (I have tried this with mysql and it worked successfully, but I had to switch over to Oracle and now I get a string representation of the ID and not the actually sequence number)
Statement stmt = conn.createStatement();
stmt.executeUpdate(insertCmd, Statement.RETURN_GENERATED_KEYS);
stmt.RETURN_GENERATED_KEYS;
ResultSet rs = stmt.getGeneratedKeys();
if(rs.next()){
log.info("Successful insert");
id = rs.getString(1);
}
The above snippet would return the column int value stored in a mysql table. But since I have switched over to Oracle, the value returned is now a strange string value.
What you're trying to do is take advantage of the RETURNING clause. Let's setup an example table and sequence:
CREATE TABLE "TEST"
( "ID" NUMBER NOT NULL ENABLE,
"NAME" VARCHAR2(100 CHAR) NOT NULL ENABLE,
CONSTRAINT "PK_TEST" PRIMARY KEY ("ID")
);
CREATE SEQUENCE SEQ_TEST;
Now, your Java code should look like this:
String insertSql = "BEGIN INSERT INTO TEST (ID, NAME) VALUES (SEQ_TEST.NEXTVAL(), ?) RETURNING ID INTO ?; END;";
java.sql.CallableStatement stmt = conn.prepareCall(insertSql);
stmt.setString(1, "John Smith");
stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
stmt.execute();
int id = stmt.getInt(2);
This is not consistent with other databases but, when using Oracle, getGeneratedKeys() returns the ROWID for the inserted row when using Statement.RETURN_GENERATEDKEYS. So you need to use the oracle.sql.ROWID proprietary type to "read" it:
Statement stmt = connection.createStatement();
stmt.executeUpdate(insertCmd, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
oracle.sql.ROWID rid = (oracle.sql.ROWID) rs.getObject(1);
But this won't give you the generated ID of the PK. When working with Oracle, you should either use the method executeUpdate(String sql, int[] columnIndexes) or executeUpdate(String sql, String[] columnNames) instead of executeUpdate(String sql, int autoGeneratedKeys) to get the generated sequence value. Something like this (adapt the value to match the index or the name of your primary key column):
stmt.executeUpdate(INSERT_SQL, new int[] {1});
ResultSet rs = stmt.getGeneratedKeys();
Or
stmt.executeUpdate(INSERT_SQL, new String[] {"ID"});
ResultSet rs = stmt.getGeneratedKeys();
While digging a bit more on this, it appears that this approach is shown in the Spring documentation (as mentioned here) so, well, I guess it can't be totally wrong. But, unfortunately, it is not really portable and it may not work on other platforms.
You should use ResultSet#getLong() instead. If in vain, try ResultSet#getRowId() and eventually cast it to oracle.sql.ROWID. If the returned hex string is actually the ID in hexadecimal flavor, then you can try converting it to decimal by Long#valueOf() or Integer#valueOf().
Long id = Long.valueOf(hexId, 16);
That said, Oracle's JDBC driver didn't support ResultSet#getGeneratedKeys() for a long time and is still somewhat troublesome with it. If you can't get that right, then you need to execute a SELECT CURRVAL(sequencename) on the same statement as you did the insert, or a new statement inside the same transaction, if it was a PreparedStatement. Basic example:
public void create(User user) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
Statement statement = null;
ResultSet generatedKeys = null;
try {
connection = daoFactory.getConnection();
preparedStatement = connection.prepareStatement(SQL_INSERT);
preparedStatement.setValue(1, user.getName());
// Set more values here.
int affectedRows = preparedStatement.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Creating user failed, no rows affected.");
}
statement = connection.createStatement();
generatedKeys = statement.executeQuery(SQL_CURRVAL);
if (generatedKeys.next()) {
user.setId(generatedKeys.getLong(1));
} else {
throw new SQLException("Creating user failed, no generated key obtained.");
}
} finally {
close(generatedKeys);
close(statement);
close(preparedStatement);
close(connection);
}
}
Oh, from your code example, the following line
stmt.RETURN_GENERATED_KEYS;
is entirely superfluous. Remove it.
You can find here another example which I posted before about getting the generated keys, it uses the normal getGeneratedKeys() approach.

Categories

Resources