How do I accept null values into the SQL Server database with Kotlin? I am trying to make that if the user does not input anything into the column, it will return null instead in the SQL Server. But I failed to do so and a bunch of numbers is saved instead, may I know how can I do it? Below are my codes and the input I got from SQL Server.
For example: 2131231267 and 2131231270 is saved instead of NULL.
fun createGoals()
{
val sqlCon = SQLCon()
checkGoal()
checkTargetAmount()
checkSavedAmount()
checkNote()
if (checkGoal() == true && checkTargetAmount() == true){
Toast.makeText(this, "Creating Goals...", Toast.LENGTH_LONG).show()
connection = sqlCon.connectionClass()!!
if(connection == null)
{
Toast.makeText(this, "Failed to make connection", Toast.LENGTH_LONG).show()
}
else {
try{
val sql :String =
"INSERT INTO Budget(gName,sAmount,Note,tAmount) VALUES ('" + binding.txtGoal.text.toString() + "'" +
",'" + Integer.valueOf(R.id.txtSavedAmount.toString()) + "'" +
",'" + R.id.txtNote.toString()+ "'" +
",'" + Integer.valueOf(binding.txtTargetAmount.text.toString().trim()) + "')"
statement = connection!!.createStatement()
statement!!.executeUpdate(sql)
Toast.makeText(this, "Going In ", Toast.LENGTH_LONG).show()
}
catch (e : Exception){
Log.e("Error", e.message!!)
}
status = true
}
}
}
private fun checkNote() : String?
{
var Note : String? = R.id.txtNote.toString()
if(Note.isNullOrEmpty())
{
Note = " "
}
return Note
}
private fun checkSavedAmount() : String?
{
var savedAmount: String? = R.id.txtSavedAmount.toString()
if(savedAmount.isNullOrEmpty())
{
savedAmount = " "
}
return savedAmount
}
Related
public static boolean CheckIsDataAlreadyInDBorNot(String TableName,
String dbfield, String fieldValue) {
SQLiteDatabase sqldb = EGLifeStyleApplication.sqLiteDatabase;
String Query = "Select * from " + TableName + " where " + dbfield + " = " + fieldValue;
Cursor cursor = sqldb.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
I constantly write an error, the database is locked. I just can not understand why this is happening.
db_login.cs
private db_controller _dbctrl = new db_controller();
public SqliteDataReader dataread;
private string query;
//this two inputField,
public void LoginToGo()
{
login = _login.captionText.text;
pass = _pass.text.ToString();
query = "SELECT id from users where users = '" + login + "' AND pass = '" + pass + "'";
try
{
dataread = _dbctrl.ExecuteReader(query);
if(dataread.HasRows & dataread != null)
{
while (dataread.Read())
{
VerifyAdmin();
_dbctrl.Disconnect();
}
}
else
{
errortxt.text = "Неверный логин или пароль, пожалуйста повторите!";
}
}
catch (Exception ex) { errortxt.text = ex.ToString(); }
}
public void VerifyAdmin() //Who are you, admin or user
{
login = _login.captionText.text;
query_access = "SELECT root from users where users = '" + login + "'";
try
{
dataread = _dbctrl.ExecuteReader(query_access);
while (dataread.Read())
{
if(dataread[0].ToString() == "0" || dataread[0].ToString() == null)
{
MainMenu();
}
else
{
AdminMenu();
}
}
}
catch (Exception ex) { errortxt.text = ex.ToString(); }
}
public void AdminMenu()
{
JOIN.SetActive(false);
ADMIN.SetActive(true);
}
public void MainMenu()
{
JOIN.SetActive(false);
MAIN.SetActive(true);
}
db_controller.cs
public SqliteConnection con_db;
public SqliteCommand cmd_db;
public SqliteDataReader rdr_db;
public void connections()
{
try
{
if(Application.platform != RuntimePlatform.Android)
{
path = Application.dataPath + "/StreamingAssets/db.bytes"; // Путь для Windows
}
else
{
path = Application.persistentDataPath + "/db.bytes"; // Путь для Android
if(!File.Exists(path))
{
WWW load = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "db.bytes");
while (!load.isDone) { }
File.WriteAllBytes(path, load.bytes);
}
}
con_db = new SqliteConnection("URI=file:" + path);
con_db.Open();
if (con_db.State == ConnectionState.Open)
{
debugText.text = path.ToString() + " - is connected";
Debug.Log(path.ToString());
}
}
catch (Exception ex)
{
debugText.text = ex.ToString();
}
}
//Тут я создаю метод отключения
public void Disconnect()
{
con_db.Close();
}
public SqliteDataReader ExecuteReader(string query)
{
connections();
try
{
cmd_db = new SqliteCommand(query, con_db);
rdr_db = cmd_db.ExecuteReader();
return rdr_db;
}
catch (Exception ex) { debugText.text = ex.ToString(); return null; }
}
//Тут я записываю данные. Заодно решил проверить закрыто ли соединение.
public void SetDB()
{
if (con_db.State == ConnectionState.Open)
{
Debug.Log("open");
}
else
{
Debug.Log("close!");
}
//The connection is closed. But I can not complete the request cmd_db.ExecuteNonQuery();
connections();
try
{
brand = AutoName.captionText.text;
model = AutoModel.captionText.text;
years = OldAuto.captionText.text;
number = GosNumber.text.ToString();
nusers = UserName.text.ToString();
dbirthday = DBirthday.captionText.text;
mbirthday = MBirthday.captionText.text;
ybirthday = YBirthday.captionText.text;
mobile = Mobile.text.ToString();
cmd_db = new SqliteCommand("INSERT INTO clients(brand,model,years,number,nusers,dbirthday,mbirthday,ybirthday,mobile,groupmodel) values('" + brand + "', '" + model + "','" + years + "','" + number + "','" + nusers + "','" + dbirthday + "','" + mbirthday + "','" + ybirthday + "','" + mobile + "','" +groupmodel+ "')" , con_db);
cmd_db.ExecuteNonQuery(); //Swears, says that the base is locked. And why? I just read the data and the connection was closed.
}
catch (Exception ex) { debugText.text = ex.ToString(); }
Disconnect();
}
the documentation says:
This error code occurs when you try to do two incompatible things with the database at the same time from the same connection to the database.
But the connection with the base is closed.
Maybe I'm missing something, or not doing the right thing. I ask for help to clarify this issue.
My function: Removes the unit in a specific row of a given Table
private static void removeUnits(String connectionString, String tableName, String columnID, String columnToFix)
{
List<String> rowsToEdit = new List<String>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT " + columnID + "," + columnToFix + " FROM " + tableName;
connection.Open();
using (var reader = command.ExecuteReader())
{
var indexOfR_MEASUREDVALUEID = reader.GetOrdinal(columnID);
var indexOfT_VALUE = reader.GetOrdinal(columnToFix);
while (reader.Read())
{
var t_value = reader.GetValue(indexOfT_VALUE);
var t_id = reader.GetValue(indexOfR_MEASUREDVALUEID);
String newValue = getWithoutUnit(t_value.ToString());
if (newValue != null)
{
String sql = "UPDATE " + tableName + " SET " + columnToFix + "='" +
newValue + "' WHERE " + columnID + "='" + t_id + "';";
rowsToEdit.Add(sql);
}
}
connection.Close();
}
}
Console.WriteLine("start writing " + rowsToEdit.Count + " entries?");
Console.ReadLine();
SqlCommand sqlCmd;
sqlCmd = new SqlCommand("", connection);
sqlCmd.Connection.Open();
foreach (String command in rowsToEdit)
{
sqlCmd.CommandText = command;
sqlCmd.ExecuteNonQuery();
}
}
Console.WriteLine(rowsToEdit.Count + " commands executed");
}
I am using C# in Visual Studio 2010 and SQL-Server 2012.
It works fine, but executing of 200000 lines takes really long.
Is its possible to do this faster?
My suggestion involves looking into parallelism:
Note: The code isn't tested, just typed it out in Notepad++
private static void removeUnits(String connectionString, String tableName, String columnID, String columnToFix)
{
List<new Tuple<object, object>> rowsToEdit = new List<new Tuple<object, object>>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT " + columnID + "," + columnToFix + " FROM " + tableName;
connection.Open();
using (var reader = command.ExecuteReader())
{
var indexOfR_MEASUREDVALUEID = reader.GetOrdinal(columnID);
var indexOfT_VALUE = reader.GetOrdinal(columnToFix);
while (reader.Read())
{
rowsToEdit.Add(new Tuple<object, object>(reader.GetValue(indexOfT_VALUE),reader.GetValue(indexOfR_MEASUREDVALUEID)));
}
connection.Close();
}
}
}
// Use parallelism here
Parallel.Foreach(rowsToEdit, currentRow =>
{
String newValue = getWithoutUnit(currentRow.Value1.ToString());
if (newValue != null)
{
// reopen connection
// use parameters here, and call SP
}
}
Console.WriteLine("start writing " + rowsToEdit.Count + " entries?");
Console.ReadLine();
}
Stored Proc:
Create StoredProcedure MySP
(
#tablename varchar(50),
#columnToFix varchar(50),
#newValue varchar(50),
#columnID varchar(50),
#tID varhcar(varchar(50)
)
As
Begin
Declare #MySQL varchar(500)
Set #MySQL = 'Update ' + #tableName + ' Set ' + #columnToFix + ' = '' + #newValue + ''' + ' Where ' + #columnID + ' = '' + #tID + '''
sp_executesql #MySQL
End
It's important to note that dynamic sql is generally frowned down upon. Here's a link discussing dynamic sql (pros/cons):http://www.sommarskog.se/dynamic_sql.html
Also it's possible you may run into some locking/contention issues b/c you're hitting one table(based on the input parameters of the function).
First try to use Parameters as already mentioned in the comments. Second, use the SqlCommand.Prepare() statement. The actual speed also depends on your machine capacities (HD Write Speed/RAM). Here is the example (you may have to edit the SqlDbTypes according to your Colum Types)
private static void RemoveUnits(string connectionString, string tableName, string columnID, string columnToFix)
{
Dictionary<int, string> rowsToEdit = new Dictionary<int, string>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT " + columnID + "," + columnToFix + " FROM " + tableName;
using (var reader = command.ExecuteReader())
{
var indexOfR_MEASUREDVALUEID = reader.GetOrdinal(columnID);
var indexOfT_VALUE = reader.GetOrdinal(columnToFix);
while (reader.Read())
{
string t_value = reader.GetString(indexOfT_VALUE);
int t_id = reader.GetInt32(indexOfR_MEASUREDVALUEID);
string newValue = getWithoutUnit(t_value);
if (newValue != null)
{
// save values in dictionary
rowsToEdit[t_id] = newValue;
}
}
}
}
Console.WriteLine("start writing " + rowsToEdit.Count + " entries?");
Console.ReadLine();
string updateCmd = "UPDATE " + tableName + " SET " + columnToFix + "= #Value WHERE " + columnID + "= #Key;";
using (SqlTransaction transaction = connection.BeginTransaction())
{
SqlCommand sqlCmd = connection.CreateCommand();
sqlCmd.CommandText = updateCmd;
sqlCmd.Parameters.Add("#Value", System.Data.SqlDbType.NVarChar, -1);
sqlCmd.Parameters.Add("#Key", System.Data.SqlDbType.Int);
// important for performance
sqlCmd.Prepare();
foreach (var update in rowsToEdit)
{
// change values of parameters
sqlCmd.Parameters["#Key"].Value = update.Key;
sqlCmd.Parameters["#Value"].Value = update.Value;
// and execute it
sqlCmd.ExecuteNonQuery();
}
transaction.Commit();
}
}
Console.WriteLine(rowsToEdit.Count + " commands executed");
}
Edit: if getWithoutUnit(string) does something not very complex, you could probably do your operation with a single statement using TSQL, which comes with various string manipulation capabilities. Like UPDATE TableName SET StringColumn = <string manipulation TSQL here>, see http://msdn.microsoft.com/en-us/library/ms181984.aspx
Edit2: added transaction from comment hint (indeed should be faster as well), strongly typed columns
I'm having issue with creating product code in recursion.
What I want to do is:
I enter code 1000
-If code exist in database regenerateCode(string code)
-else insert into database
Code:
(...)
if(codeExist)
CodeTB.Text = regenerateCode(string toParse); //toParse = 1000
string regenerateCode(string toParse)
{
string helper = "";
int parseCode = int.Parse(toParse);
helper = new string('0', 4 - parseCode.ToString().Length);
helper += parseCode + 1;
using (SqlConnection conn = new SqlConnection(cString.c_String))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT Product.productID FROM Product " +
"WHERE Product.PLU = '" + helper + "' ", conn))
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
// if code still exist in database, regenerate it
regenerateCode(helper);
}
else
{
//else return code
return helper;
}
}
}
}
return helper;
}
Actually it works fine with example:
1000 (exist)
1001 (exist)
1002 (not exist, insert), but
when code = 1002, it goes into line with else {return helper;} and have no idea why going again to regenerateCode() method..
Any ideas?
It happens because you do nothing with the return value. You pass helper to the recursion, but do not place the return value anywhere. your method should look like this:
string regenerateCode(string toParse)
{
string helper = "";
int parseCode = int.Parse(toParse);
helper = new string('0', 4 - parseCode.ToString().Length);
helper += parseCode + 1;
using (SqlConnection conn = new SqlConnection(cString.c_String))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT Product.productID FROM Product " +
"WHERE Product.PLU = '" + helper + "' ", conn))
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// Return the next code that doesn't exist
return rdr.HasRows ? regenerateCode(helper) : helper;
}
}
}
}
Also, remember that while string are reference types, they are immutable. which means that a string that is passed as an argument would not change like a normal array. see: How are strings passed in .NET?
I have some links on a page such as:
< a id="Digg" runat="server">< img alt="Digg" id="imgDigg" runat="server" src="~/resources/images/icons/social/digg_32.png" border="0" />< /a>
I have a database table that can "turn" them on or off, in my code behind I have the following:
string[] SocialMedia = new string[] { "Twitter", "Facebook", "LinkedIn", "Digg", "Email", "Print" };
private void CheckForSocialMedia()
{
int i = 0;
for (i = 0; i < SocialMedia.Length; i++)
{
bool AddSocialMedia = (bool)AllowSocialMedia(SocialMedia[i]);
if (AddSocialMedia == false)
{
// Hide the link: Digg.Visible = false;
}
}
}
protected bool AllowSocialMedia(string sSocialMedia)
{
SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConn"].ConnectionString);
SqlCommand myCommand = myConnection.CreateCommand();
myCommand.CommandText = " select Settings.AllowsocialMedia " +
" from ArticleSocialMediaSettings Settings " +
" inner join SocialMedia on Settings.SocialMediaId = SocialMedia.id " +
" where SocialMedia.NetworkName = '" + sSocialMedia + "'" +
" and Settings.RetailerId = '1234'";
myConnection.Open();
try
{
SqlDataReader myReader = myCommand.ExecuteReader();
if (myReader.Read())
{
return (bool)myReader["AllowsocialMedia"];
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
How can I hide the link if the function returns false? Or is there a better way to do this?
It looks like that is the correct method for checking the database. To hide the link you can use:
document.getElementById("Digg").style.display = "none";
right where your comment is.
Redesigned it using a datalist