I want to insert 6406 recods into a table in one swoop without having to prepare and execute individual records. (fastest). In the code below, I want "i" to change for every insert
Ive tried everything
for( int i = 0; i < 6406 ; i++)
{
sprintf( query, "INSERT INTO table1"
"(table_id, curr_id, cur_ref_id) "
"VALUES (%d,%d,%d)",
table_id,
i,
table_id);
//assemble query
DBH->prepare(query);
}
DBH->execute();
Inset prepare failed for table1
My memory of the MySQL C API is a bit fuzzy, but IIRC it should look something like:
MYSQL_STMT* stmt = mysql_stmt_init(MYSQL *mysql);
mysql_stmt_prepare(stmt,
"INSERT INTO table1 (table_id, curr_id, cur_ref_id) VALUES (?,?,?)",
len_of_previous_argument);
MYSQL_BIND params[3];
memset(params, 0, sizeof(params));
params[0].buffer_type = MYSQL_TYPE_LONG;
params[1].buffer_type = MYSQL_TYPE_LONG;
params[2].buffer_type = MYSQL_TYPE_LONG;
params[0].buffer = &table_id;
params[2].buffer = &table_id;
mysql_bind_param(stmt, params);
mysql_autocommit(conn, 0);
for ( int i = 0; i < 6406 ; i++) {
params[1].buffer = &i;
mysql_stmt_execute(stmt);
}
mysql_commit(conn);
mysql_stmt_close(stmt);
You'll obviously want to throw in some error handling, but this should give you the basic idea.
It might be faster to only have one parameter and encode the table_id values in the query string instead, but I'm lazy and you obviously know how to do that already (snprintf should have "(%d,?,%d)", then pass the result to mysql_stmt_prepare, then the params array will only be a single item).
Related
I am doing a procedure to loop over specific field names for 2 reasons:
I want to hash the field name itself using md5 (We are working with data vault);
I want to add each field name value as a row in the table.
I have the following procedure which is working perfect:
CREATE PROCEDURE ADD_OBSERVATION_VALUES()
RETURNS string
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
arr = [];
var row_num = 1;
// Set the indicators
COLUMN_FIELD_NAMES = ["care_beneficiary", "cg_child_6mo_receiv_ind_iycf_nbr_1st_cons_6mc_iycfc number",
"preg_women_rec_ind_counselling_nbr_1st_cons_pregw_iycfc",
...
];
COLUMN_FIELD_NAMES_TO_HASH = [
"cg_child_6mo_receiv_ind_iycf/nbr_1st_cons_6mc_iycfc",
"cg_child_6mo_receiv_ind_iycf/nbr_followup_2nd_time_6mc_iycfc",
...
];
try{
// while(rows_result.next()){
for (var col_num = 0; col_num<COLUMN_FIELD_NAMES_TO_HASH.length; col_num = col_num+1){
var COL_NAME = COLUMN_FIELD_NAMES_TO_HASH[col_num];
var query = "INSERT INTO LINK_OBSERVATION_FIELD SELECT (SELECT md5(concat(?, concat('CAMP', concat(CAMPNO, DATE))))), current_timestamp(), (SELECT 'ONA'), (SELECT (md5(concat(DATE, concat('CAMP', CAMPNO))))), md5(?) FROM IYCF_TEMP";
var stmt = snowflake.createStatement( {sqlText: query, binds:[COL_NAME, COL_NAME]} );
if(stmt.execute()){
// var query = "INSERT INTO SAT_FIELD_VALUES SELECT (SELECT (md5(md5(concat(?, concat('CAMP', concat(CAMPNO, DATE))))))), current_timestamp(), NULL, (SELECT 'ONA'), ?, (SELECT 'PENDING'), (SELECT _SUBMISSION_TIME), (SELECT md5(concat(?, concat('CAMP', concat(CAMPNO, DATE))))) FROM IYCF_TEMP";
// var stmt = snowflake.createStatement( {sqlText: query, binds: [COL_NAME, COL_NAME, COL_NAME] });
// stmt.execute()
}
}
// }
return "DONE"
}
catch(error){
return error
}
$$;
The first insert query is working fine, when it goes to the second insert query after successful execution, I get the following error:
Numeric value 'care_beneficiary' is not recognized
I am guessing that the error is coming from , ?, of the below insert query:
INSERT INTO SAT_FIELD_VALUES SELECT (SELECT (md5(md5(concat(?, concat('CAMP', concat(CAMPNO, DATE))))))), current_timestamp(), NULL, (SELECT 'ONA'), ?, (SELECT 'PENDING'), (SELECT _SUBMISSION_TIME), (SELECT md5(concat(?, concat('CAMP', concat(CAMPNO, DATE))))) FROM IYCF_TEMP;
The ? within the CONCATS are working fine, but the standalone field , ?, . In this standalone binded field, I want to get its value from the table not its name, and I am assuming that it is because the field is being read as with quotes, and the query is considering it string that should not be added to a numeric field.
Any idea how to remove quotes or let the query treat it as field name and not as a value?
The solution was as mentioned by Felipe in the comment section of the question, to bind and compose the query with strings and variables:
var query = "SELECT ... " + COL_NAME + "FROM ..."
Apparently IDENTIFIER(COL_NAME) didn't work for me but I am sure that it will work if I knew where to use the binding.
I'm trying to write my first mySql stored procedure and keep on getting an error from the server that I am unable to understand, hope someone will be able to help me fixing it.
What I am doing
I collect some parameters from social networks, and I need to save this data in two different tables. I know that the table schema might not be optimal, but this is something I cannot change at the moment.
The idea is that I call the stored procedure from my server-side code passing in article ID and some other parameters, and the procedure:
Updates the "articles" table
Inserts anew record into the "popularity" tables with some values that are the result of the previous UPDATE
This is the stored procedure I wrote
BEGIN
UPDATE
articles2
SET
fb_shares = n_shares,
fb_comments = n_comments,
fb_reactions = n_reactions,
tw_tweets = #tweets :=(tw_tweets + n_tweets),
tw_retweets = #retweets :=(tw_retweets + n_retweets),
tw_favorites = #favorites :=(tw_favorites + n_favorites),
tw_reach = #reach :=(tw_reach + n_reach),
tw_since_id = n_since_id,
popularity = #popularity :=(
(n_shares * fb_shares_weight) +(
n_comments * fb_comments_weight
) +(
n_reactions * fb_reactions_weight
) +(#tweets * tw_tweets_weight) +(#retweets * tw_retweets_weight) +(
#favorites * tw_favorites_weight
) +(#reach * tw_reach_weight)
),
popularity_updated =(popularity_updated + 1)
WHERE
id = n_id ;
INSERT
INTO
popularity(
article_id,
added,
popularity,
tw_tweets,
tw_reach,
tw_favorites,
tw_retweets,
tw_since_id,
fb_shares,
fb_comments,
fb_reactions
)
VALUES(
n_id,
NOW(), #popularity, #tweets, #reach, #favorites, #retweets, n_since_id, n_shares, n_comments, n_reactions) ;
END
I keep getting an error #1416 - Cannot get geometry object from data you send to the GEOMETRY field and the INSERT is never performed. I suppose that the variables assignment is wrong, but cannot understand how to fix it.
As said, I never wrote a stored procedure before, and since that line looks correct to me, I really cannot understand what's wrong. I cannot exclude that I am trying to do something that should not be done with a stored procedure, but the few examples that I found online makes me think this should be correct...
Thank you in advance,
Simone
Edit:
I got rid of that error, but still the INSERT is not performed... here is the updated stored procedure:
BEGIN
SET #tweets := 0, #retweets := 0, #favorites := 0, #reach := 0, #popularity := 0;
UPDATE
articles2
SET
fb_shares = n_shares,
fb_comments = n_comments,
fb_reactions = n_reactions,
tw_tweets = #tweets :=(tw_tweets + n_tweets),
tw_retweets = #retweets :=(tw_retweets + n_retweets),
tw_favorites = #favorites :=(tw_favorites + n_favorites),
tw_reach = #reach :=(tw_reach + n_reach),
tw_since_id = n_since_id,
popularity = #popularity :=(
(n_shares * fb_shares_weight) +(
n_comments * fb_comments_weight
) +(
n_reactions * fb_reactions_weight
) +(#tweets * tw_tweets_weight) +(#retweets * tw_retweets_weight) +(
#favorites * tw_favorites_weight
) +(#reach * tw_reach_weight)
),
popularity_updated =(popularity_updated + 1)
WHERE
id = n_id ;
SELECT #tweets, #retweets, #favorites, #reach, #popularity;
INSERT
INTO
popularity(
article_id,
added,
popularity,
tw_tweets,
tw_reach,
tw_favorites,
tw_retweets,
tw_since_id,
fb_shares,
fb_comments,
fb_reactions
)
VALUES(
n_id,
NOW(), #popularity, #tweets, #reach, #favorites, #retweets, n_since_id, n_shares, n_comments, n_reactions) ;
END
Check the definition of the popularity table for a field defined with data type GEOMETRY and change to appropriate type.
I am using Spring-Jdbc template(first timer) to create MySql repository. I have tables that use AutoIncrement columns as primary key.
I wonder if there a way to get newly generated Ids (autoInc) with each successful batch create statement?
Any pointers or sample would be a great help.
Thanks
Panks
Use getGeneratedKeys() method from your Statement or PreparedStatement object to identify the new auto generated values. Iterate the returned ResultSet object to get the newly generated key values in the order of batch statements.
This call may throw java.sql.SQLFeatureNotSupportedException if the JDBC driver, that you are using, does not support this method.
Sample code snippet:
String sql_insert =
"insert into my_table ( non_auto_incrmnt_fld_names_,_separated ) " +
" values ( record1 ), ( record2 )"; // append as many as required
...
int rowsAffected = stmtObject.executeUpdate( sql_insert, Statement.RETURN_GENERATED_KEYS );
ResultSet rs = stmtObject.getGeneratedKeys();
//******************************************************
rs.last();
int rows = rs.getRow();
System.out.println( "Generated keys count: " + rows );
int currentRow = 1;
rs.beforeFirst();
//******************************************************/
while( rs.next() ) {
System.out.println( /**/( currentRow++ ) + " = " + /**/rs.getInt( 1 ) );
} // while rs
I read a set of data from database first
Insert a new record using same data in same table.
I tried this but:-
using (var db = new
DataContext(ConfigurationManager.ConnectionStrings["DB"].ToString()))
{
var items = from t in db.Table1
where t.ID.Equals(100)
select t;
foreach (var item in items)
{
using (var db1 = new
DataContext(ConfigurationManager.ConnectionStrings["DB"].ToString()))
{
Table1 tab = new Table1
{
FName = item.FName,
LName = item.LName,
Number = item.Number,
};
db1.Table1.InsertAllOnSubmit(tab);
db1.SubmitChanges();
}
}
}
I can't compile it. It throws this error at line 'db1.Table1.InsertAllOnSubmit(tab)':-
'System.Data.Linq.Table.InsertAllOnSubmit(System.Collections.Generic.IEnumerable)'
cannot be inferred from the usage. Try specifying the type arguments
explicitly.
Your code has some flaws.
You seem to read one Table1 (assuming the id is unique) but you are treating it like a collection
Quick try since you anyway add only one table1 at a time: Replace
db1.Table1.InsertAllOnSubmit(tab);
by
db1.Table1.InsertOnSubmit(tab);
If your ID is not unique try:
List<Table1> items = (from t in db.Table1
where t.ID.Equals(100)
select t).ToList();
The rest of the code can stay the same (but still replace the InsertAllOnSubmit)
Update
You can simplify bigtime:
using (var db = new
DataContext(ConfigurationManager.ConnectionStrings["DB"].ToString()))
{
Table1 thisTable = (from t in db.Table1
where t.ID. == 100
select t).SingleOrDefault();
if ( thisTable != null)
{
Table1 tab = new Table1 ()
{
FName = item.FName,
LName = item.LName,
Number = item.Number, };
db.Table1.InsertOnsubmit(tab)
db.SubmitChanges();
}
}
}
if you are 100% sure your id will always match use .Single() instead of .SingleOrDefault(). Single will throw an exception if no result matches. SingleOrDefault returns NULL in this case.
Let's say I have a table with 3 columns: C1, C2, C3
I make a search based on the C1 column.
Could I make something similar like this (this is not working - because this is not the way prepareStatement it's used:) )
String c;// the name of the column
...
String sql = "select * from table where ? = ?";
pre = con.prepareStatement(sql);
pre.setString(1, c);
pre.setString(1, i);
rs = pre.executeQuery();
The main idea, I don't want to have 3 ifs for every column. An elegant solution?
This won't work. The prepare statement parses the SQL, sends to the database for validation and compilation. If question marks could substitute parts of the SQL, you would loose the whole point of bound variables - speed and security. You would reintroduce SQL injection back and statements will have to be recompiled for all parameters.
Wouldn't something like SELECT * FROM table WHERE c1 = ? OR c2 = ? OR c3 = ? be better (of course depending on indexes and table sizes).
you could code up a a set of sql queries and store them in a map, then grab one based on the column in question.
enum column { a, b, c}
Map<column, string> str;
static {
str.put(a, "select * from tbl where a = ? ");
...
}
then just grab one out of the map later based on the enum. String appends in sql statements have a way of becoming security problems in the future.
Use a dynamic query and a java.sql.Statement:
String whereClause = c + " = " + i;
// Form the dynamic Query
StringBuffer query = new StringBuffer( "SELECT * FROM TABLE" );
// Add WHERE clause if any
query.append(" WHERE " + whereClause);
// Create a SQL statement context to execute the Query
Statement stmt = con.createStatement();
// Execute the formed query and obtain the ResultSet
ResultSet resultSet = stmt.executeQuery(query.toString());
can't you do this:
String c;// the name of the column
...
String sql = "select * from table where " + c + " = ?";
pre = con.prepareStatement(sql);
pre.setString(1, i);
rs = pre.executeQuery();
?
If not then this might be a solution:
String c;// the name of the column
...
String sql = "select * from table where ('C1' = ? AND C1 = ?)
OR ('C2' = ? AND C2 = ?)
OR ('C3' = ? AND C3 = ?)"
pre = con.prepareStatement(sql);
pre.setString(1, c);
pre.setString(2, i);
pre.setString(3, c);
pre.setString(4, i);
pre.setString(5, c);
pre.setString(6, i);
rs = pre.executeQuery();