First I query some data from user A and then I need to insert all this data to user B (user in oracle I mean) and I use Java to solve it. Below is my code:
while (ds.getResultSet().next()) {
ResultSet resultSet = ds.getResultSet();
ResultSetMetaData metaData = resultSet.getMetaData();
int count = metaData.getColumnCount();
StringBuilder sb = new StringBuilder();
sb.append("insert into ");
sb.append(tableName.toUpperCase());
sb.append("(");
for (int i = 1; i <= count; i++) {
sb.append(metaData.getColumnName(i));
if (i != count) sb.append(",");
else sb.append(")");
}
sb.append(" values(");
for (int i = 1; i <= count; i++) {
Object colValue = resultSet.getObject(i);
if (colValue == null) {
sb.append("null");
} else {
if (colValue instanceof Date) {
Date d = resultSet.getDate(i);
String dateStr = DateUtils.formatDate(d, "yyyy-MM-dd hh:mm:ss");
sb.append("to_date(");
sb.append("'");
sb.append(dateStr);
sb.append("','yyyy-MM-dd hh24:mi:ss')");
} else {
sb.append("'");
sb.append(resultSet.getObject(i));
sb.append("'");
}
}
if (i != count) sb.append(",");
else sb.append(")");
}
conn = datasource.getConnection();
System.out.println(sb.toString());
ps = conn.prepareStatement(sb.toString());
ps.execute();
}
So it works a bit, but when it inserts above 80 records oracle just collaspses, and it's warning me in the console:
Can you guys give some advice to me about this? Thanks for your time.
Do not use Java - just do it all in Oracle.
INSERT INTO b.table_name ( col1, col2, col3, col4 )
SELECT col1, col2, col3, col4
FROM a.table_name
WHERE some_column = some_value; -- Add filters if necessary
You avoid having to dynamically build the query by parsing the meta-data.
You avoid errors where you are not escaping single quotes.
Further to this, you avoid potential SQL Injection attacks where a user could enter something like the string value', (SELECT password_hash FROM users WHERE userid = 'Admin1' ) ) --
As you guys suggest, I changed my code like below:
Connection conn = DriverManager.getConnection(url, user, pwd);
PreparedStatement pspt = conn.prepareStatement("select * from SYS_DICT_TYPE");
ResultSet resultSet = pspt.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
StringBuilder sql = new StringBuilder();
sql.append("insert into TEST_SYS (");
for (int i = 1; i <= columnCount; i++) {
sql.append(metaData.getColumnName(i));
if (i != columnCount) sql.append(",");
}
sql.append(") values(");
for (int i = 1; i <= columnCount; i++) {
sql.append("?");
if (i != columnCount) sql.append(",");
}
sql.append(")");
String s = sql.toString();
PreparedStatement pspt2 = conn.prepareStatement(s);
while (resultSet.next()) {
for (int i = 1; i <= columnCount; i++) {
pspt2.setObject(i, resultSet.getObject(i));
}
pspt2.addBatch();
}
pspt2.executeBatch();
The wired thing is: At the first I build the statement end with a ';'
(the sql clause should like insert into tablename values(?,?);)
which cause ora-00933:SQL error.When I removed the ';' it worked perfectly well.Why could this happend?
Related
The environment is React, .NET Core 2.2.5, Oracle EF Core 2.19.30, Oracle 12c.
I am using the following code to add change log entries whenever an entity is changed in some way. Everything I've seen on Google indicates this should work. However, when it gets to the "base.SaveChanges()" call, I get the error "database operation expected to affect 1 row(s) but actually affected 5 row(s)". If I remove the change log code and just call "base.SaveChanges()", it works fine and does update the expected row, so the issue is clearly related to the change log entries itself.
I've seen this error on Google, but the actual number is always 0, never more. The other strange thing is that every time I run the code, the "actual" number increases by 5 (I'm up to 95 at the moment, and that's after I rebooted), which does happen to be the number of change log entries that should be added.
I don't see anything unusual in my situation, other than I'm using Oracle (I plan on testing this with SQL Server at home soon).
public override int SaveChanges()
{
List<EntityEntry> entries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted).ToList();
foreach (EntityEntry entry in entries.ToArray())
{
string tableName = new SafetyDataContext().Model.FindEntityType(entry.Entity.GetType()).Relational().TableName;
string keyData = GetPrimaryKeyValue(entry);
if (entry.State == EntityState.Added)
{
PropertyValues currentValues = entry.CurrentValues;
for (int i = 0; i < currentValues.Properties.Count; i++)
{
string columnName = currentValues.Properties[i].Relational().ColumnName;
string newValue = currentValues[currentValues.Properties[i].Name] != null ? currentValues[currentValues.Properties[i].Name].ToString() : string.Empty;
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "ADD",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = string.Empty,
New_Value = newValue
};
this.Changes.Add(log);
}
}
else if (entry.State == EntityState.Modified)
{
PropertyValues currentValues = entry.CurrentValues;
PropertyValues originalValues = entry.OriginalValues;
for (int i = 0; i < currentValues.Properties.Count; i++)
{
string columnName = currentValues.Properties[i].Relational().ColumnName;
string oldValue = entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name) != null ? entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name).ToString() : string.Empty;
string newValue = currentValues[currentValues.Properties[i].Name] != null ? currentValues[currentValues.Properties[i].Name].ToString() : string.Empty;
if (oldValue != newValue)
{
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "CHANGE",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = oldValue,
New_Value = newValue
};
this.Changes.Add(log);
}
}
}
else if (entry.State == EntityState.Deleted)
{
PropertyValues originalValues = entry.OriginalValues;
for (int i = 0; i < originalValues.Properties.Count; i++)
{
string columnName = originalValues.Properties[i].Relational().ColumnName;
string oldValue = entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name) != null ? entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name).ToString() : string.Empty;
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "DELETE",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = oldValue,
New_Value = string.Empty
};
this.Changes.Add(log);
}
}
}
return base.SaveChanges();
}
This is the correct example, which does not work:
If the LANGUAGE column is the same as the LANGUAGE COLUMN and the NLS_CLASS_NAME column is the same as the KEYWORD COLUMN
Given that they are true, if you noticed the language string I turned it into lowercase and I cut the string so that it becomes "en", since it was first ENG
You must print the language list, keyword is translation
I noticed that it takes a long time to start up, then it prints continuously but incorrectly, because it doesn't print the translation in the for loop.
Can you help me kindly?
I noticed that it takes a long time to start up, then it prints continuously but incorrectly, because it doesn't print the translation in the for loop.
Can you help me kindly?
//Traduzione in Db2 a SqlServer
public void getTraduzione() throws Exception {
List<DizioPt> listDizio = new ArrayList<DizioPt>();
List<ClassHdrNls> listHdr = new ArrayList<ClassHdrNls>();
String className = "";
String language = "";
String nlsClassName = "";
String lingua = "";
String keyword = "";
String traduzione = "";
Database database = new Database();
// Db2
Connection dbConnectionDb2 = null;
Statement statementDb2 = null;
// SqlServer
Connection dbConnectionSqlServer = null;
Statement statementSqlServer = null;
// Query Db2
String queryDb2 = "select * from THERA.CLASS_HDR_NLS WHERE
THERA.CLASS_HDR_NLS.LANGUAGE='en'";
// Query SqlServer
String querySqlServer = "select * from DIZIOPT WHERE
DIZIOPT.LINGUA='ENG'";
try {
// Connessione --> SqlServer
dbConnectionSqlServer = database.getConnectionSqlServer();
statementSqlServer = dbConnectionSqlServer.createStatement();
// Connessione -->Db2
dbConnectionDb2 = database.getConnectionDb2();
statementDb2 = dbConnectionDb2.createStatement();
// Risultato SqlServer
ResultSet rsSqlServer = statementSqlServer.executeQuery(querySqlServer);
// Risultato Db2
ResultSet rsDb2 = statementDb2.executeQuery(queryDb2);
while (rsSqlServer.next() && rsDb2.next()) {
ClassHdrNls classHdrNls = new ClassHdrNls();
className = rsDb2.getString("CLASS_NAME");
classHdrNls.setClassName(className);
language = rsDb2.getString("LANGUAGE");
classHdrNls.setLanguage(language);
nlsClassName = rsDb2.getString("NLS_CLASS_NAME");
classHdrNls.setNlsClassName(nlsClassName);
listHdr.add(classHdrNls);
DizioPt diziopt = new DizioPt();
lingua = rsSqlServer.getString("LINGUA");
diziopt.setLingua(lingua);
keyword = rsSqlServer.getString("KEYWORD");
diziopt.setKeyword(keyword);
traduzione = rsSqlServer.getString("TRADUZIONE");
diziopt.setTraduzione(traduzione);
listDizio.add(diziopt);
for (int i = 0; i < listHdr.size(); i++) {
for (int j = 0; j < listDizio.size(); j++) {
if (listHdr.get(i).getNlsClassName().equalsIgnoreCase(listDizio.get(j).getKeyword())
&& listHdr.get(i).getLanguage()
.equalsIgnoreCase(listDizio.get(j).getLingua().toLowerCase().substring(0, 2))) {
System.out.println("Class name: " + listHdr.get(i).getClassName());
System.out.println("Lingua: " + listHdr.get(i).getLanguage());
System.out.println("Testo: " + listHdr.get(i).getNlsClassName());
System.out.println("Traduzione: " + listDizio.get(j).getTraduzione());
}
}
}
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (statementDb2 != null && statementSqlServer != null) {
statementDb2.close();
statementSqlServer.close();
}
if (dbConnectionDb2 != null && dbConnectionSqlServer != null) {
dbConnectionDb2.close();
dbConnectionSqlServer.close();
}
}
}
BigDecimal baseAmt = Env.ZERO;
String sql = "SELECT il.LineNetAmt, COALESCE(il.TaxAmt,0), i.IsSOTrx "
+ "FROM C_InvoiceLine il"
+ " INNER JOIN C_Invoice i ON (il.C_Invoice_ID=i.C_Invoice_ID) "
+ "WHERE il.C_Invoice_ID=? AND il.C_Tax_ID=?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, get_TrxName());
pstmt.setInt (1, getC_Invoice_ID());
pstmt.setInt (2, getC_Tax_ID());
rs = pstmt.executeQuery ();
/*MInvoiceLine[] lines1 = getLines(false);
for (int a = 0; a < lines1.length; a++)
{MInvoiceLine sLine = lines1[a];*/
while (rs.next ())
{
MInvoiceLine[] lines1 = getLines(false);
for (int a = 0; a < lines1.length; a++)
{
MInvoiceLine sLine = lines1[a];
// BaseAmt
baseAmt = rs.getBigDecimal(1);
for (int j = 0; j < cTaxes.length; j++)
{
/*if (!iTax.calculateTaxFromLines1())
return false;*/
MTax cTax = cTaxes[j];
BigDecimal taxAmt = cTax.calculateTax1(baseAmt, isTaxIncluded(), getPrecision());
MInvoiceTaxLine newITax = new MInvoiceTaxLine(getCtx(), 0, get_TrxName());
MProduct product = MProduct.get (getCtx(), sLine.getM_Product_ID());
newITax.setClientOrg(this);
newITax.setC_Invoice_ID(getC_Invoice_ID());
newITax.setC_Tax_ID(cTax.getC_Tax_ID());
//newITax.setPrecision(getPrecision());
//newITax.setIsTaxIncluded(isTaxIncluded());
newITax.setBaseAmount(sLine.getPriceEntered());
newITax.setM_Product_ID(product.getName());
newITax.setBaseAmount(baseAmt);
newITax.setCaculatedTaxAmt(taxAmt);
newITax.saveEx(get_TrxName());
//
if (!isTaxIncluded())
grandTotal = grandTotal.add(taxAmt);
}
}
}
}
catch (SQLException e)
{
throw new DBException(e, sql);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
}
In above code excution is 1) query the goes in to while loop , and second for loop but i want first it should line1 and second time it should go to while then inside it shloud take second value of line.
Please help me out
In AX Report the User can select different Range. I seek to show that the criteria used to filter user in the report itself even
the expression "parameter!CustomerAccount.Value" don't work because this filter is not a static parameter.
the user can use any table from the query and any field from the table and any criteria.. I'm locking for trick to get for which table, which field and what criteria it uses.
this method work very well ^_^
(( I use it privet and not static ))
static void getQueryRanges2(Args _args)
{
Query query;
QueryRun queryRun;
QueryBuildDataSource qbd;
QueryBuildRange range;
QueryFilter filter;
int cnt, filtercnt, i,j, k;
DictTable dictTable;
DictField dictField;
str fieldLabel;
;
query = new query(queryStr(smmSalesCustItemStatistics));
queryRun = new QueryRun(query);
queryRun.prompt();
query = queryRun.query(); for(i = 1; i <= query.dataSourceCount(); i++)
{
cnt = query.dataSourceNo(i).rangeCount();
filtercnt = 0;
if(!query.dataSourceNo(i).embedded())
{
filtercnt = query.queryFilterCount(query.dataSourceNo(i));
}
dictTable = new DictTable(query.dataSourceNo(i).table());
for (k=1; k<= filtercnt; k++)
{
filter = query.queryFilter(k, query.dataSourceNo(i));
dictField = new DictField(query.dataSourceNo(i).table(), fieldname2id(query.dataSourceNo(i).table(), filter.field()));
info (strFmt("%1, %2. Range = %3", dictTable.label(), dictField.label(), filter.value()));
}
for (j=1; j<=cnt; j++)
{
range = queryRun.query().dataSourceNo(i).range(j);
dictField = new DictField(query.dataSourceNo(i).table(), fieldname2id( query.dataSourceNo(i).table(), range.AOTname()));
if(range.value())
{
info(strfmt("%1, %2. Range = %3",dictTable.label(), dictField.label(), range.value()));
}
}
}
}
enjoy :)
How can I project the row number onto the linq query result set.
Instead of say:
field1, field2, field3
field1, field2, field3
I would like:
1, field1, field2, field3
2, field1, field2, field3
Here is my attempt at this:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
{
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
{
int i = 1;
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select new ScoreWithRank()
{
Rank=i++,
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
};
return query.ToList<ScoreWithRank>();
}
}
Unfortunately, the "Rank=i++" line throws the following compile-time exception:
"An expression tree may not contain an assignment operator"
Well, the easiest way would be to do it at the client side rather than the database side, and use the overload of Select which provides an index as well:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
{
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
{
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select new
{
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
};
return query.AsEnumerable() // Client-side from here on
.Select((player, index) => new ScoreWithRank()
{
PlayerName = player.PlayerName,
PlayerScore = player.PlayerScore,
Rank = index + 1;
})
.ToList();
}
}
Ok, that did the trick. Thanks.
Here is my final code...
Server:
public List<Score> GetHighScores(string gameId, int count)
{
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
{
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select s;
return query.ToList<Score>();
}
}
Client:
void hsc_LoadHighScoreCompleted(object sender, GetHighScoreCompletedEventArgs e)
{
ObservableCollection<Score> list = e.Result;
_listBox.ItemsSource = list.Select((player, index) => new ScoreWithRank()
{
PlayerName = player.PlayerName,
PlayerScore = player.PlayerScore,
Rank = index+=1
}).ToList();
}
You could also make just a slight adjustment to your original code to get it working. Word of caution, if you databind or access the object again, the Rank will increment each time. In those cases the top answer is better.
let Rank = i++
and
Rank.ToString()
Full code:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
{
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
{
int i = 1;
var query = from s in entities.Scores
let Rank = i++
where s.Game.Id == guid
orderby s.PlayerScore descending
select new ScoreWithRank()
{
Rank.ToString(),
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
};
return query.ToList<ScoreWithRank>();
}
}
This solution worked for me.
http://www.dotnetfunda.com/articles/article1995-rownumber-simulation-in-linq.aspx
.Select((x, index) => new
{
SequentialNumber = index + 1
,FieldFoo = x.FieldFoo
}).ToList();
List<Emp> Lstemp = GetEmpList();
int Srno = 0;
var columns = from t in Lstemp
orderby t.Name
select new {
Row_number=++Srno,
EmpID = t.ID,
Name = t.Name,
City = t.City
};