Prevent duplicate results in SQL - c#

I have a combo box (comboBox1) in my application that lists catagories from my SQL database. It is pulling the data correctly at the moment. My only problem is that when the data is listed in the combo box, there are duplicate results. For example:
What I want it to list:
Example 1
Example 2
Example 3
What it actualy lists:
Example 1
Example 1
Example 1
Example 1
Example 1
Example 2
Example 2
Example 2
Example 3
Example 3
Example 3
Here is the code that I am using to list the data:
public void ListCat()
{
DataTable linkcat = new DataTable("linkcat");
using (SqlConnection sqlConn = new SqlConnection(#"Connection stuff;"))
{
using (SqlDataAdapter da = new SqlDataAdapter("SELECT name FROM list WHERE name <> 'NULL'", sqlConn))
{
da.Fill(linkcat);
}
}
foreach (DataRow da in linkcat.Rows)
{
comboBox1.Items.Add(da[0].ToString());
}
}
In short, my question would be how can I prevent duplicate data from being listed?

Use DISTINCT . It will eliminate the duplicate records.
Change your query to
SELECT DISTINCT name FROM list WHERE name <> 'NULL'
Assuming you may have stored the string value NULL inside your name column for some records.
If you have the real NULL in the name field, your query should be like this
SELECT DISTINCT name FROM list WHERE name is not NULL

Use DISTINCT
SELECT DISTINCT name FROM list WHERE name <> 'NULL'

Add a group by to the SELECT statement.
SELECT name FROM list WHERE name <> 'NULL' GROUP BY name

Related

Words are added to the end of a column

In my database, each letter has its own column, but when I add words to the column, it goes to the bottom and Null fields are created
Now so
And I need it this
I have a list of words and the word must fall into the column from which the first letter of the word begins
My Code
private void ConnectData()
{
_path = "URI=file:" + Application.streamingAssetsPath + "/russianWords.db"; //Path to datab
_dbConnection = new SqliteConnection(_path);
_dbConnection.Open();
if (_dbConnection.State == ConnectionState.Open)
{
m_sqlCmd = new SqliteCommand();
m_sqlCmd.Connection = _dbConnection;
m_sqlCmd.CommandText = "CREATE TABLE IF NOT EXISTS words (а Text , б Text ,в Text,г Text,д Text,е Text,ё Text,ж Text,з Text,и Text,й Text,к Text,л Text,м Text,н Text,о Text,п Text,р Text,с Text,т Text,у Text,ф Text,х Text,ц Text,ч Text,ш Text,щ Text,ъ Text,ы Text,ь Text,э Text,ю Text,я Text)";
m_sqlCmd.ExecuteNonQuery();
}
AddToData("sddd", "т");
}
public void AddToData(string word)
{
try
{
m_sqlCmd.CommandText = $#"INSERT INTO words ('{word.ToCharArray()[0].ToString()}') values ('{ word }')";
m_sqlCmd.ExecuteNonQuery();
}
catch (System.Exception e)
{
Debug.Log(e);
}
}
Databases don't work like this. Putting data in a table will always make a new row. It is not like a game of upwards- Tetris where you insert "Fred" into column "F" and it will find the first empty slot (nearest the "top") and put it there. There isn't even the sense of "top" - datatable tables are just a bunch of rows stored in whatever order the database feels like. If you want your data to have an order you must insert some data that has an order (like an int) and sort by it
If you want this "Tetris" style behavior you must program it explicitly. Have a column that is incrementing numbers
ID A B C
1
2
You want to insert Apple. Select the lowest ID where the column is blank
SELECT MIN(id) FROM t WHERE A IS NULL
ExecuteScalar that and cast the result to an int?
If there is an ID, update it. Otherwise insert:
UPDATE t SET A = 'Apple' WHERE ID = 1
ID A B C
1 Apple
2
Now we want to insert Aeroplane. It will go in ID 2 by the same logic
ID A B C
1 Apple
2 Aeroplane
Now we insert Aurora. There is no row 3. The SELECT that finds the ID will return no rows (you'll get a null returned from execute scalar)
Run the following insert
INSERT INTO t(ID, A)
SELECT MAX(id)+1, 'Aurora' FROM t
ID A B C
1 Apple
2 Aeroplane
3 Aurora
You now have aurora in ID 3
Continue thus either inserting or updating. You should thus have at least one column that is completely full all the time and the others will fill in as they go..
--
Consider to use any auto numbering facility your chosen db has rather than max+1 (but max+1 would work)

Save all records from one table column in an array

I want to store all records from a MySQL table column in an array (C#).
E.g. if there is the column "name" in a table:
name
other column
...
Peter
Marc
Henry
... I want to store these names as elements in an array/list programmatically. The goal is to be able to access each element (in this case name) itself and going on with that.
Using a MySqlDataReader didn't work out that good, because it only returned me the last record in the column:
conn.Open();
string getNameQuery = "SELECT * FROM myTable";
MySqlCommand getName = new MySqlCommand(getNameQuery, conn);
dataReader = getName.ExecuteReader();
while(dataReader.Read())
{
dataReader.getString("name");
}
conn.Close();
Create a List and add the values to it.
List<string> ls = new List<string>();
while(dataReader.Read())
{
ls.Add(dataReader.GetString("name"));
}
Also, as I suggested, if you need only name column then write the query SELECT name FROM myTable. There is no need to fetch other columns.

Create column from another table dynamically

I'm working with TSQL and C#. I have two queries that return strings:
string[] allSubcategories = dt.AsEnumerable().Select(x => x.Field<string>("SubcategoryName")).Distinct().ToArray();
var redMark = db.GetTableBySQL("SELECT * FROM RedMarkItems");
string[] redMarkColumns = redMark.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray();
So, as you can see I have two different arrays, first I get subcategoriesNames:
and all columns of table RedMarkItems:
That I want to do is to create column dynamically, I mean, if subcategorieName does not exist as column in RedMarkItems do an Update and create it someting like:
var createColumn = db.ExeSQL($"ALTER TABLE RedMarkItems ADD {ColumnName} BIT");
How can I compare if subcategorieName does not exist as column in RedMarkItems table? Then create column as my query? Regards
If you want to know if a particular column exists in an already filled DataTable using the Linq approach then it is just:
bool exists = redMark.Columns.Cast<DataColumn>().Any(x => x.ColumnName == "SubCategoryName");
Instead, if you want to ask this info directly to the database then use the INFORMATION_SCHEMA views The Columns view is the one to use with a query like this.
string query = #"IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.Column
WHERE Column_Name = #colName)
SELECT 1 ELSE SELECT 0";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.Add("#colName", SqlDbType.NVarChar).Value = "SubCategoryName";
bool exists = (cmd.ExecuteScalar() == 1);
Now, the part about creating the column is pretty simple as code per se. It is just an appropriate ALTER TABLE. But there are a lot of things to be cleared before. What will be the datatype of the new column? What will be its length and precision? What will be the constraints applied to it (Null/Not Null defaults etc)? As you can see all these info are very important and require to be defined somewhere in your code.

TableMappings With TableName Instead of TableN

I am not sure this is possible, but I just cant figured it out.
I have a SP in my DB as below:
CREATE PROCEDURE [dbo].[GetMyValue]
AS
SELECT Code, TypeDesc FROM IDType
SELECT Code, Race FROM Race
SELECT Code, Nation FROM Nationality
SELECT Code, [Language name] AS 'Language' FROM Languages
SELECT Code, Occupation FROM Occupation
SELECT Code, Country FROM Country
GO
What I am trying to do is map the table with the table name from DB like this:
Dim da As New SqlDataAdapter(cmd)
da.TableMappings.Add("IDType", "NRICType")
da.TableMappings.Add("Race", "Race")
da.TableMappings.Add("Nationality", "Nationality")
da.TableMappings.Add("Languages", "Languages")
da.TableMappings.Add("Occupation", "Occupation")
da.TableMappings.Add("Country", "Country")
da.Fill(ds)
instead of using TableN like this:
Dim da As New SqlDataAdapter(cmd)
da.TableMappings.Add("Table", "NRICType")
da.TableMappings.Add("Table1", "Race")
da.TableMappings.Add("Table2", "Nationality")
da.TableMappings.Add("Table3", "Languages")
da.TableMappings.Add("Table4", "Occupation")
da.TableMappings.Add("Table5", "Country")
da.Fill(ds)
Anyway, it doesn't seem working as when I try to access the value in the later part with Dim dt As DataTable = ds.Tables("NRICType"). The ds.Tables("NRICType") appears to be NULL. Everything work fine when I map it with TableN.
But the problem might happen in future is, what if the sequence of SELECT STATEMENT in SP changed? The mapping will definitely mess up. Code in C# would help too.
Chinz,
Here is a Hack that will give you what you are looking for...
In your Stored procedure add one additional field (TableName) to your selects
CREATE PROCEDURE [dbo].[GetMyValue]
AS
SELECT 'IDType' TableName, Code, TypeDesc FROM IDType
SELECT 'Race' TableName, Code, Race FROM Race
SELECT 'Nationality' TableName, Code, Nation FROM Nationality
SELECT 'Languages' TableName, Code, [Language name] AS 'Language' FROM Languages
SELECT 'Occupation' TableName, Code, Occupation FROM Occupation
SELECT 'Country' TableName, Code, Country FROM Country
GO
Now in your c# code after the da.Fill(ds)
da.Fill(ds);
for (int i = 0; i < ds.Tables.Count; i++)
{
if (i == 0)
da.TableMappings.Add("table", GetTableName(i, ds));
else
da.TableMappings.Add("table" + i.ToString(), GetTableName(i, ds));
}
GetTableName is a method to grab the first field from the DataTable
static string GetTableName(int tableIndex, DataSet ds)
{
if (ds.Tables[tableIndex].Rows.Count > 0)
return ds.Tables[tableIndex].Rows[0]["TableName"].ToString();
// If there aren't any rows I don't know the Table name and return table[index] as the name
return "table" + tableIndex.ToString();
}
Another way to do this is to make you first selection in the Stored Procedure the order and name of the Tables. Then in your c# code after the the da.Fill(ds) you can read the rows out of ds.tables[0] and use that for your table mappings.
I hope this helps.
If you don't want to deal with additional unwanted columns in your results, then consider the following
Your Stored Procedure will have an additional select which will be the first select and define the order of the tables being returned.
CREATE PROCEDURE [dbo].[GetMyValue]
AS
SELECT 'IDType' TableName, 1 as SortOrder
UNION
SELECT 'Race' TableName , 2 as SortOrder
UNION
SELECT 'Nationality' TableName , 3 as SortOrder
UNION
SELECT 'Languages' TableName ,4 as SortOrder
UNION
SELECT 'Occupation' TableName , 5 as SortOrder
UNION
SELECT 'Country' TableName, 6 as SortOrder
ORDER BY SortOrder
SELECT Code, TypeDesc FROM IDType
SELECT Code, Race FROM Race
SELECT Code, Nation FROM Nationality
SELECT Code, [Language name] AS 'Language' FROM Languages
SELECT Code, Occupation FROM Occupation
SELECT Code, Country FROM Country
GO
and in the c# code after the da.Fill(ds) do this
//string[] listOfTableNames;
listOfTableNames = GetTableNames(ds);
for (int i = 0; i < ds.Tables.Count; i++)
{
da.TableMappings.Add("table" + i.ToString(), listOfTableNames[i]);
}
and GetTableNames Method is defined as
static string[] GetTableNames( DataSet ds)
{
List<string> tablenames = new List<string>();
// The first Table contains the TABLE NAMES
tablenames.Add("TableNames");
if (ds.Tables[0].Rows.Count > 0)
foreach( DataRow row in ds.Tables[0].Rows)
{
tablenames.Add(row["TableName"].ToString());
}
return tablenames.ToArray();
}
As described in the documentation in MSDN thats the way it is supposed to be used.
http://msdn.microsoft.com/en-us/library/ms810286.aspx
If the Stored procedure is setup in that order, that order must be maintained in the future.
If you want to make this Dynimac you could verify the table schema and try to identify if you are looking at the correct table, but this will add a big cost in performance.
Dim da As New SqlDataAdapter(cmd)
da.TableMappings.Add("Table", "NRICType")
da.TableMappings.Add("Table1", "Race")
da.TableMappings.Add("Table2", "Nationality")
da.TableMappings.Add("Table3", "Languages")
da.TableMappings.Add("Table4", "Occupation")
da.TableMappings.Add("Table5", "Country")
da.Fill(ds)
Your second example is the correct use for this feature.

Taking Value of dropdownlist in asp.net

After using inner joins and fetching data from 3 tables I want to show course names that are assigned to Miss Jennifer whise Tchr_ID is 4 , ddlcourse is dropdown list id
SqlCommand cmd = new SqlCommand(#"
SELECT
Course.Course_name,
Tchr_course_ID
FROM Course
INNER JOIN CourseOffering
ON Course.Course_ID=CourseOffering.Course_ID
INNER JOIN Tchr_Course
ON Tchr_Course.Course_offer_ID=CourseOffering.Course_offer_ID
where Tchr_Course.Tchr_ID = 4", conn);
SqlDataReader dr = cmd.ExecuteReader();
ddlcourse.DataSource = dr;
ddlcourse.Items.Clear();
ddlcourse.DataTextField = "Course_name";
ddlcourse.DataValueField = "Tchr_course_ID";
ddlcourse.DataBind();
After fetching I am showing dropdown textfield as course name and I am applying datavaluefiled as tch_Course_ID because when user will select the course , its tchr_course_ID will be saved in db. to save id I am using ddlcourse.SelectedItem.Value but this gives me error in my insert statement about foreign key. It is not taking value of selected course. Why? and how can I correct it?
These tables are involved in it..
Course table:(which have courses list in it) ==>
(Course_ID,Course_name)
CourseOffering table: (which have record that these courses are
offered this semester) ==> > (Course_offer_ID, Course_ID)
Tchr_Course table: (which have record that this course is assigned to
this teacher) ==> (Tchr_course_ID, Course_offer_ID, Tchr_ID)
Profile table: (simple contains teacher record) == >
(Tchr_ID,NAme,Email)
Use SelectedValue instate of using SelectedItem.Value since ur ddlcourse has DataValueField as Tchr_course_ID hence only SelectedValue gives u required result for Tchr_course_ID.

Categories

Resources