I develop a program who save a picture. But I get this error message:
Cannot insert the value NULL into column 'Id'
private void savepicture()
{
if(pictureBox1.Image != null)
{
MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat);
byte[] a = ms.GetBuffer();
ms.Close();
cm.Parameters.Clear();
cm.Parameters.AddWithValue("#picture", a);
cm.CommandText = "insert into Bild (FileName,Datei) values ('" + label1.Text.ToString() + "',#picture )";
sc.Open();
cm.ExecuteNonQuery(); // i get here the error message
sc.Close();
label1.Text = "";
pictureBox1.Image = null;
MessageBox.Show("Bild wurde gespeichert !");
}
}
Before anything you should check for a structure of your table Bild,
there you probably have a column called Id which is constraint and can not be a null.
And by reading your code I can not see on next line that you are supplying 'Id' to your sql:
cm.CommandText = "insert into Bild (FileName,Datei) values ('" + label1.Text.ToString() + "',#picture )";
What you should do here is next:
Send id from your code to a sql (create variable and include it in insert command) depending of your column type (int, guid or whatever, so if you are using int you should incremet your variable which will hold value for next 'Id' in your database, or if it is Guid you should create new Guid for every new row using Guid.NewGuid method )
Edit id column on Sql and apply AUTO_INCREMENT keyword to perform an auto-increment feature, example :
Alter TABLE Bild(
id int NOT NULL AUTO_INCREMENT,
rest of columns
);
Or you might apply next steps in case you are using Microsoft SQL and I guess you do because I can see you are using SqlCommand.CommandText Property in your C# code.
Presumably you are in the design of the table. If not: right click the
table name - "Design". Click the required column. In "Column
properties" (at the bottom), scroll to the "Identity Specification"
section, expand it, then toggle "(Is Identity)" to "Yes".
I cannot add comments so i will answer here.
If your Id is the primary key, you either insert it yourself or use the identity option (auto increment):
add the identity option to the key from ssms. If you want to do it by query follow the answer given here https://dba.stackexchange.com/questions/128433/add-autoincrement-to-existing-pk
in your insert statement do insert into Bild (Id,FileName,Datei) values ([your id], 'val1', 'val2').
Note: You have to specify the Id you want to insert if your primary key does not have an way of doing it itself (auto increment)
Related
I am trying to add some columns in an access database using Oledb Command. The type of the column are different, like Currency(OleDbType.Currency), float with two decimal place (OleDbType.Numeric), integer(OleDbType.Integer) etc. the below code is what I am using to accomplish my task... But each and every time it Shows error Message saying Some..".. Error in Field Definition.." or as I change code sometime it shows "Syntax Error in Column Definition .." etc.
var insertColumnCommand = #"ALTER TABLE ProductRecordsTable ADD COLUMN [Price]= #ProductPrice, [Shipped(NoS)]= #ProductShippedNumber, [Returned(NoS)]= #ProductReturnedNumber, [Sold(NoS)]= #ProductSoledNumber, [Tax Percentage]= #ProductTaxPercentage";
var con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\MyDatabase.accdb;Jet OLEDB:Database Password= 12345;");
using(con)
{
var cmd = new OleDbCommand(insertColumnCommand, con);
if (con.State == ConnectionState.Closed)
con.Open();
cmd.Parameters.Add("#ProductPrice", OleDbType.Currency);
cmd.Parameters.Add("#ProductShippedNumber", OleDbType.Integer);
cmd.Parameters.Add("#ProductReturnedNumber", OleDbType.Integer);
cmd.Parameters.Add("#ProductSoledNumber", OleDbType.Integer);
var parameter = new OleDbParameter("#ProductTaxPercentage",OleDbType.Numeric);
parameter.Precision = 6;
parameter.Scale = 2;
cmd.Parameters.Add(parameter);
cmd.ExecuteNonQuery();
con.Close();
}
I would also like to add option like putting NULL value in already existing rows of the table in the newly added columns, and 0(Zero) will be inserted as default value, for the rows that will be added later on.But the cmd.ExecuteNonQuery(); like is too stubborn to not run successfully.
As said in comments above, you cannot use parameters when you execute Data Definition Language commands like ALTER TABLE (this is true in any database I known of) In your specific case you can use the DECIMAL datatype for the columns that requires scale and precision values and no = between the name of the column and the type.
#"ALTER TABLE ProductRecordsTable
ADD COLUMN [Price] DECIMAL (10,2),
[Shipped(NoS)] INT,
[Returned(NoS)] INT,
[Sold(NoS)] INT,
[Tax Percentage] DECIMAL (6,2)";
Then suppose you want to set the Price to be NOT NULL. First execute a query to set every row to a predefined value
"UPDATE ProductRecordsTable SET Price = 0"
And now set the NOT NULL value on the column
#"ALTER TABLE ProductRecordsTable ALTER COLUMN [Price] DECIMAL (10,2) NOT NULL"
If you want to set a default value (for new records on some column
#"ALTER TABLE ProductRecordsTable ALTER COLUMN [Sold (NoS)] INT DEFAULT 0"
Using Text Area I'm sending Values to database by clicking button, but I want postID to auto generate how I can do it?
protected void btnPost_Click(object sender, EventArgs e)
{
string PostQuery = "INSERT INTO [Post] (PostID,PostDet,Votes,UserID) VALUES('<auto Genatare post ID>','" + TxtPost.Text + "','12','Us001')";
dbClass.ConnectDataBaseToInsert(PostQuery);
Response.Redirect("~/computing.aspx");
}
You could make PostID a UNIQUEIDENTIFIER column and then pass in a newly generated GUID (Guid.NewGuid()).
Also, please use parameterized queries to avoid SQL injection. Especially if the inputs come directly from WEB users.
To do so, change your ConnectDataBaseToInsert method to not take SQL text, but an SqlCommand which you prepare with the respective parameters.
From your comment to the question: The PostID should be like PO0001. Then the only way to do it properly and to respect for concurrency is to generate a stored procedure that takes the value to insert, which generates the ID itself.
To do so, create a new table that contains the last post ID. Then, use an UPDATE ... OUTPUT statement to increment and return in one go. This is the only way to do an atomic update of the post ID so that no two users create the same ID.
Example Table PostIDTable
Current
=======
0
Example SELECT to update and retrieve the current post ID:
-- We need a temp table, because OUTPUT can not output into a single variable
-- This increments Current by one and outputs the value that was set in one go.
-- This prevents simultaneous calls to get the same ID
DECLARE #postID (ID INT)
UPDATE PostIDTable
OUPUT INSERTED.Current INTO #postID
SET
Current = Current + 1
-- Get the value from the temp table and convert it into the desired format
DECLARE #pID INT = (SELECT TOP 1 ID FROM #postID)
DECLARE #id NVARCHAR(6) = 'PO' + RIGHT('0000' + CONVERT(NVARCHAR, #pID), 4)
-- Do the actual INSERT
INSERT INTO (PostDet, Votes,UserID) VALUES (#id, ..., ...)
You should make the PostID column to be an IDENTITY(1,1) column (in case of using MSSQL. server). So when you will insert new rows to your database the corresponding PostID values will be autogenerated by your database. The same holds for each other RDBMS you may use.
Having done the above change you code will change to the following:
protected void btnPost_Click(object sender, EventArgs e)
{
string PostQuery = "INSERT INTO [Post] (PostDet,Votes,UserID) VALUES("TxtPost.Text + "','12','Us001')";
dbClass.ConnectDataBaseToInsert(PostQuery);
Response.Redirect("~/computing.aspx");
}
If PostId is autogenerated, only do this:
protected void btnPost_Click(object sender, EventArgs e)
{
string PostQuery = "INSERT INTO [Post] (PostDet,Votes,UserID) VALUES('" + TxtPost.Text + "','12','Us001')";
dbClass.ConnectDataBaseToInsert(PostQuery);
Response.Redirect("~/computing.aspx");
}
Removing PostId from your query, it will generate the next Id
the best way is to use auto increment column ID for your table.
Please, see w3school tutorial where is described construction for all main db.
Try this..
select * from tablename order by id desc limit 1
where id would be your primary key attribute name.
I am using dapper.rainbow for inserting a record into MSSQL db. Following is my code
int? id = db.RoomTypes.Insert(roomType)
When i run my app, i am getting the below exception.
Cannot insert explicit value for identity column in table 'RoomTypes'
when IDENTITY_INSERT is set to OFF.
I think that dapper.rainbow is using the value (default value for int) for my Identity Column during the insert. This is what causing this exception. My identity column for the table RoomTypes is auto incremented and it is also the primary key of my table.
Now, how do i stop the dapper.rainbow from using the ID column during insert.
Looking at the Dapper.Rainbow.Insert method, the method is "dumb" to the type passed in as the data parameter:
public virtual int? Insert(dynamic data)
{
var o = (object)data;
List<string> paramNames = GetParamNames(o);
string cols = string.Join(",", paramNames);
string cols_params = string.Join(",", paramNames.Select(p => "#" + p));
var sql = "set nocount on insert " + TableName + " (" + cols + ") values (" + cols_params + ") select cast(scope_identity() as int)";
return database.Query<int?>(sql, o).Single();
}
In other words, if you include the ID as a property in the parameter, then Dapper will try to insert that value into the database. And as you've seen, if you have IDENTITY_INSERT set to Off, then the insert will fail.
This means you'll need to create a new type that doesn't include your ID property to pass into the method. A few of ideas come to mind:
Create a base class without the ID for RoomTypes and then just pass in the base class to the Insert method.
Create a dynamic parameter and pass that to the Insert method with only the properties you want to insert into the database.
Override the Insert method and remove the ID parameter before sending to the Dapper
I have two tables one is members table with columns member id , member first name, member last name. I have another table guest passes with columns guest pass id and member id and issue date .
I have a list view that will displays guest passes details (I.e) like member name and issue date and I have two text boxes those are for entering member name and issue date .
member name text box is auto complete text box that working fine....
but the problem is when I am entering the name that is not in member table at this time it will accept and displays a blank field in list view in member name column and member id is stored as "0" in guest pass table ......
I don't want to display the member name empty blank and I don t want to store "0" in guest pass table
and this is the insert statement
sql2 = #"INSERT INTO guestpasses(member_Id,guestPass_IssueDate)";
sql2 += " VALUES(";
sql2 += "'" + tbCGuestPassesMemberId.Text + "'";
sql2 += ",'" + tbIssueDate.Text + "'";
guestpassmemberId = memberid
is there any validation that need to be done
and this is the auto complete text box statement
sql = #"SELECT member_Id FROM members WHERE concat(member_Firstname,'',member_Lastname) ='" + tbMemberName.Text+"'";
dt = GetData(sql, mf);
if (dt != null)
{
if (dt.Rows.Count > 0)
{
tbCGuestPassesMemberId.Text = Convert.ToInt32(dt.Rows[0] ["member_Id"]).ToString();
}
}
can any one help me on this ...
is there any type of validation with sql query
pls help me .....
You can validate the values before passing them to the INSERT. Additionally you can also set a constraint to validate versus a regular expression in SQL.
SQL constraints
To validate before inserting you should have something like this:
private void validateData(Long memberId) {
//Pseudo code Depends on how you are connecting to your database...
SQLQuery query = getQuery("existsMemberId");
query.setParameter("memberId");
executeQuery(query);
// If the query returns something then the reference exists and it is ok to proceed
}
In the file you are storing your queries...
#existsMemberId
select 1
from members mem
where mem.id = :id <-- parameter
Additionally you should make foreign key constraint between members and guest passes with ID as the foreign key:
ALTER TABLE GuestPasses
ADD CONSTRAINT fk_memberId
FOREIGN KEY (id)
REFERENCES Members(id)
I know that in Oracle I can get the generated id (or any other column) from an inserted row as an output parameter.
Ex:
insert into foo values('foo','bar') returning id into :myOutputParameter
Is there a way to do the same, but using ExecuteScalar instead of ExecuteNonQuery?
I don't want to use output parameters or stored procedures.
ps: I'm using Oracle, not sql server!!!
If you are on oracle, you have to use ExecuteNonQuery and ResultParameter. There is no way to write this as query.
using (OracleCommand cmd = con.CreateCommand()) {
cmd.CommandText = "insert into foo values('foo','bar') returning id into :myOutputParameter";
cmd.Parameters.Add(new OracleParameter("myOutputParameter", OracleDbType.Decimal), ParameterDirection.ReturnValue);
cmd.ExecuteNonQuery(); // an INSERT is always a Non Query
return Convert.ToDecimal(cmd.Parameters["myOutputParameter"].Value);
}
Oracle uses sequences as for his identity columns, if we may say so.
If you have set a sequence for your table primary key, you also have to write a trigger that will insert the Sequence.NextValue or so into your primary key field.
Assuming that you are already familiar with this concept, simply query your sequence, then you will get your answer. What is very practiced in Oracle is to make yourself a function which will return an INT, then within your function, you perform your INSERT. Assuming that you have setup your trigger correctly, you will then be able to return the value of your sequence by querying it.
Here's an instance:
CREATE TABLE my_table (
id_my_table INT PRIMARY KEY
description VARCHAR2(100) NOT NULL
)
CREATE SEQUENCE my_table_seq
MINVALUE 1
MAXVALUE 1000
START WITH 1
INCREMENT BY 2
CACHE 5;
If you want to manage the auto-increment yourself, here's how:
INSERT INTO my_table (
id_my_table,
description
) VALUES (my_table_seq.NEXTVAL, "Some description");
COMMIT;
On the other hand, if you wish not to care about the PRIMARY KEY increment, you may proceed with a trigger.
CREATE OR REPLACE TRIGGER my_table_insert_trg
BEFORE INSERT ON my_table FOR EACH ROW
BEGIN
SELECT my_table_seq.NEXTVAL INTO :NEW.id_my_table FROM DUAL;
END;
Then, when you're inserting, you simply type the INSERT statement as follows:
INSERT INTO my_table (description) VALUES ("Some other description");
COMMIT;
After an INSERT, I guess you'll want to
SELECT my_table_seq.CURRVAL
or something like this to select the actual value of your sequence.
Here are some links to help:
http://www.orafaq.com/wiki/Sequence
http://www.orafaq.com/wiki/AutoNumber_and_Identity_columns
Hope this helps!
You can use below code.
using (OracleCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"INSERT INTO my_table(name, address)
VALUES ('Girish','Gurgaon India')
RETURNING my_id INTO :my_id_param";
OracleParameter outputParameter = new OracleParameter("my_id_param", OracleDbType.Decimal);
outputParameter.Direction = ParameterDirection.Output;
cmd.Parameters.Add(outputParameter);
cmd.ExecuteNonQuery();
return Convert.ToDecimal(outputParameter.Value);
}
one possible way if one can add one column named "guid" to the table :
when inserting one record from c#, generate a guid and write it to the guid column.
then perform a select with the generated guid, and you have got the id of inserted record :)
Select t.userid_pk From Crm_User_Info T
Where T.Rowid = (select max(t.rowid) from crm_user_info t)
this will return your required id