Using SQL Server 2005, vb.net
Table1
Name FromDate ToDate
Raja 12/02/2010 14/02/2010
Ravi 14/02/2010 15/02/2010
Ramu 18/02/2010 21/02/2010
...,
Insert into Table1 values('" & textbox1.text & "', '" & textbox2.text & "'. '" & textbox3.text & "'", con)
When i try to insert a value into table1 it will compare the table values if it is same, It Should throw a error msg "Name and Date Already Exist" otherwise Insert a value.
Before Inserting i want to check a textbox value with table value.
Can any one give a sample idea or code for this.
In T-SQL:
IF EXISTS(SELECT * FROM dbo.Table1 WHERE Name = #Name AND FromDate = #FromDate AND ToDate = #ToDate)
RAISERROR (N'Values already exist', 10, 1)
ELSE
INSERT INTO dbo.Table1(Name, FromDate, ToDate)
VALUES(#Name, #FromDate, #ToDate)
And then call this from a parametrized query in your VB.NET code.
For details about RAISERROR, see the MSDN docs: http://msdn.microsoft.com/en-us/library/ms178592.aspx. The value "10" here is the severity, the "1" is the state. You can see a list of all available severities and states in the MSDN docs.
Or wrap the whole statement into a stored proc that deals with all of this, and just call that stored proc.
UPDATE:
Create a stored proc:
CREATE PROCEDURE dbo.InsertData(#Name VARCHAR(50), #FromDate DATETIME, #ToDate DAETIME)
AS BEGIN
BEGIN TRANSACTION
IF EXISTS(SELECT * FROM dbo.Table1 WHERE Name = #Name AND FromDate = #FromDate AND ToDate = #ToDate)
ROLLBACK TRANSACTION
RAISERROR (N'Values already exist', 10, 1)
ELSE
INSERT INTO dbo.Table1(Name, FromDate, ToDate)
VALUES(#Name, #FromDate, #ToDate)
COMMIT TRANSACTION
END
and then call that from your code (I'm not fluent in VB.NET - this is C#, but should be simple enough to translate):
using(SqlConnection _con = new SqlConnection('your connection string here'))
{
using(SqlCommand _cmd = new SqlCommand("InsertData", _con)
{
_cmd.CommandType = CommandType.StoredProcedure;
// add parameters as necessary
_cmd.Parameters.AddWithValue("#Name", "Your Name");
_cmd.Parameters.AddWithValue("#FromDate", "20100101");
_cmd.Parameters.AddWithValue("#ToDate", "20100331");
try
{
// open connection, execute stored proc, close connection
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
catch(SqlException sqlexc)
{
// handle SQL exception
}
}
}
That nicely encapsulates everything into a single method - does that work for you??
Use the "IF NOT EXIST" command
IF NOT EXISTS (SELECT * FROM Table WHERE YourContition) INSERT INTO Table (a,b) VALUES (#c1,#c2)
Related
I have been using a Stored Procedure created by our DB guy, who happens to be out of town for the next week. The SP used to work, but before he left, the DB guy edited the SP, causing my code to throw a server error: "Column name or number of supplied values does not match table definition". He claimed before he left the SP should mainly be the same, so I'm at a loss for why it's no longer matching.
Here is the c# code:
System.Data.SqlClient.SqlCommand objCmd = new
System.Data.SqlClient.SqlCommand("dci.webDonorStatistics", objConn);
objCmd.CommandTimeout = 950;
objCmd.CommandType = System.Data.CommandType.StoredProcedure;
objCmd.Parameters.Add(new
System.Data.SqlClient.SqlParameter("#FiscalYear", 2018));
GridView1.DataSource = objCmd.ExecuteReader();
GridView1.DataBind();
Here is the declaration of the SP:
ALTER PROCEDURE [dci].[webDonorStatistics] #FiscalYear INT
AS
BEGIN
--DECLARE #FiscalYear INT = 2018
DECLARE
#StartDate DATE = CONVERT(DATE, '01-OCT-' + CONVERT(CHAR(4), #FiscalYear - 1))
, #EndDate DATE = DATEADD(DAY, -1, GETDATE())
IF #EndDate >= CONVERT(DATE, '30-SEP-' + CONVERT(CHAR(4), #FiscalYear))
SELECT #EndDate = CONVERT(DATE, '30-SEP-' + CONVERT(CHAR(4), #FiscalYear))
ELSE
SELECT #EndDate = DATEADD(DAY, -1, CONVERT(DATE, '01-' + DATENAME(MONTH, GETDATE()) + '-' + CONVERT(CHAR(4), YEAR(GETDATE())))) -- End of previous month
IF DATEDIFF(DAY, #StartDate, #EndDate) < 0
SELECT #EndDate = GETDATE()
BEGIN TRY
DROP TABLE #webDonorStatistics
END TRY
BEGIN CATCH
END CATCH
Any help would be greatly appreciated. Thanks in advance.
First step is to isolate your error. Is your error thrown from your application code or database code?
If you follow 3Dave's suggestion, what do you get? Assuming you are pointed to the correct database server. Try running:
EXEC [dci].[webDonorStatistics] 2018
If the above call does not return any error, I would check the application code.
Your Error indicates that the data which you are trying to insert into the table is not valid, You would have to right-click on the stored procedure and click on execute stored procedure where you can insert the parameter for the fiscal year, The execution should fail. Then create a copy of same stored procedure with a different name and change the data type for the fiscal year and see if that would fix the issue and give you the result when you execute the stored procedure. Also on the Stored Proc could which you have I dont see any insert commands if there are any try checking the data type of what you are trying to insert and the data type of what is present inside the table schema if that doesn't match then you can change accordingly .
I'm trying to use dapper to parameterize a postgres anonymous function i've written to do an upsert. Here's the code:
private static int UpsertProductPrice(
IDbConnection connection,
Data.ProductPrice price,
List<Data.ProductPriceTier> priceTiers)
{
string postgres = #"DO $$
BEGIN
UPDATE product_price
SET start_date = #StartDate, end_date = #EndDate, price_tier_type = #PriceTierType
WHERE product_price_external_id = #Id;
IF found THEN
RETURN;
END IF;
BEGIN
INSERT INTO product_price(product_price_external_id, start_date, end_date, price_tier_type)
VALUES (#Id, #StartDate, #EndDate, #PriceTierType);
RETURN;
EXCEPTION WHEN unique_violation THEN END; END$$;";
int productPriceId = connection.Execute(
postgres,
new { Id = price.product_price_external_id, StartDate = price.start_date, EndDate = price.end_date, PriceTierType = price.price_tier_type });
Postgres logs the query as unparameterized: there are still # signs and no values were inserted. Here's the log.
2015-07-15 14:57:58.570 EDT,"user","TestDb",8496,"::1:53953",55a6ad36.2130,1,"DO",2015-07-15 14:57:58 EDT,9/42,0,ERROR,42703,"column ""startdate"" does not exist",,,"UPDATE product_price
SET start_date = #StartDate, end_date = #EndDate, price_tier_type = #PriceTierType
WHERE product_price_external_id = #Id",52,"PL/pgSQL function inline_code_block line 3 at SQL statement","DO $$
BEGIN
UPDATE product_price
SET start_date = #StartDate, end_date = #EndDate, price_tier_type = #PriceTierType
WHERE product_price_external_id = #Id;
IF found THEN
RETURN;
END IF;
BEGIN
INSERT INTO product_price(product_price_external_id, start_date, end_date, price_tier_type)
VALUES (#Id, #StartDate, #EndDate, #PriceTierType);
RETURN;
EXCEPTION WHEN unique_violation THEN END; END$$;",,,""
I'm I doing something wrong, or is this not supported? I couldn't find anyone trying to do this online.
Parameters in anonymous code blocks aren't supported, this would be a PostgreSQL feature rather than an Npgsql feature. See discussion here: https://github.com/npgsql/npgsql/issues/629
I have a database structured as follows:
users
userid (Primary Key)
username
group
groupid (PK)
groupName
user_groups
userid (Foreign Key)
groupid (Foreign Key)
The first time a user logs in I would like their info to be added to the users table. So essentially the logic I would like to have if
if (//users table does not contain username)
{
INSERT INTO users VALUES (username);
}
How can I do this intelligently using SQL Server/C# ?
Or using the new MERGE syntax:
merge into users u
using (
select 'username' as uname
) t on t.uname = u.username
when not matched then
insert (username) values (t.uname);
Basically you can do it like this:
IF NOT EXISTS (SELECT * FROM USER WHERE username = #username)
INSERT INTO users (username) VALUES (#username)
But seriously, how you're going to know if user visited your website for the first time?
You have to insert records in table user, when somebody register on your website, not login.
IF NOT EXISTS (select * from users where username = 'username')
BEGIN
INSERT INTO ...
END
I would first create a stored proc on the db to do the check and insert if necessary:
CREATE PROCEDURE AddNewUserProc
(
#username VarChar(50) -- replace with your datatype/size
)
AS
IF NOT EXISTS (SELECT * FROM users WHERE username = #username)
BEGIN
INSERT INTO users
VALUES (#username)
END
Then a method on the app that will call this procedure
public void AddNewUserMethod(string userName)
{
SqlConnection connection = new SqlConnection("connection string");
SqlCommand command = new SqlCommand("AddNewUserProc", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("username", SqlDbType.VarChar, 50).Value = userName;
try
{
connection.Open();
command.ExecuteNonQuery();
}
finally
{
if (connection.State == ConnectionState.Open) { connection.Close(); }
}
}
Note leaving this as alternative/historical, but for purpose of correctness the correct way is using the Merge statement, see answer https://stackoverflow.com/a/9649040/167304 or checkout MS doc https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver15
There is a simple solution! I Found it in this post!
INSERT INTO users (Username)
SELECT ('username')
WHERE NOT EXISTS(SELECT * FROM users WHERE Username= 'username')
In my project I needed to do it with 2 values. So my code was:
INSERT INTO MyTable (ColName1, ColName2)
SELECT 'Value1','Value2'
WHERE NOT EXISTS
(SELECT * FROM MyTable WHERE ColName1 = 'Value1' AND ColName2= 'Value2')
Hope this helps!
The following code is a method that returns 0 if user already exists and returns the new user ID that just added :
private int TryToAddUser(string UserName)
{
int res = 0;
try
{
string sQuery = " IF NOT EXISTS (select * from users where username = #username) \n\r" +
" BEGIN \n\r" +
" INSERT INTO users values (#username) \n\r" +
" SELECT SCOPE_IDENTITY() \n\r " +
" END \n\r " +
" ELSE SELECT 0";
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand())
{
cmd.CommandText = sQuery;
cmd.Parameters.AddWithValue("#username",UserName);
cmd.Connection = new System.Data.SqlClient.SqlConnection("SomeSqlConnString");
cmd.Connection.Open();
res = (int)cmd.ExecuteScalar();
cmd.Connection.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return res;
}
#gbn answer needs SQL server 2008 or higher. I tried a non-merge way to do it. Ugly perhaps, but it works.
declare #user varchar(50)
set #user = 'username'
insert into users (username)
select #user
where not exists (
select username
from users
where username = #user
);
If you want to test any of the answers, here is the SQL for the table -
CREATE TABLE [dbo].[users](
[userid] [int] NULL,
[username] [varchar](50) NULL
)
INSERT [dbo].[users] ([userid], [username]) VALUES (1, N'John')
INSERT [dbo].[users] ([userid], [username]) VALUES (2, N'David')
INSERT [dbo].[users] ([userid], [username]) VALUES (3, N'Stacy')
INSERT [dbo].[users] ([userid], [username]) VALUES (4, N'Arnold')
INSERT [dbo].[users] ([userid], [username]) VALUES (5, N'Karen')
Here is a (probably oversimplified) example that addresses your issue. Note that it is always best to use parameters to prevent injection attacks, especially when verifying users.
CREATE PROCEDURE AddUser
#username varchar(20)
AS
IF NOT EXISTS(SELECT username FROM users WHERE username=#username)
INSERT INTO users(username) VALUES (#username)
Why doesn't this work? I get an error saying the number cannot be infinity. However, I had to take this away from an insert statement so that it doesn't post entries twice.
Where do I have to incorporate this piece of code to get it to allow my code to loop as a new ID?
cmd = new SqlCommand(#"SELECT CAST(scope_identity() as int)", con);
int aID = Convert.ToInt32(cmd.ExecuteScalar());
In general you can have a stored procedure to do the INSERT and return the last inserted identity with an out parameter, as you can see in an example here: http://www.objectreference.net/post/SCOPE_IDENTITY()-return-the-id-from-the-database-on-insert.aspx
CREATE PROCEDURE [dbo].[Customer_Insert]
#Name VARCHAR(255),
#Email VARCHAR(255),
#Phone VARCHAR(255),
#CustomerID INT OUTPUT
AS
BEGIN
INSERT INTO dbo.Customer ([Name], Email, Phone)
VALUES (#Name,#Email,#Phone)
SET #CustomerID = CAST(SCOPE_IDENTITY() AS INT)
END
I am using asp.net, .NET 3.5, C#, and SQL Server Express 2005.
I have created a stored procedure in SQL, and when I run SP from SQL server it takes less than 1 second to return results. I have also tried that query in query analyzer and it also gives me results in less than 1 second. But when I try to call this SP from .NET (C#), it takes a long time, and then gives a timeout error.
Here is the code I am using to call the stored procedure:
SqlConnection con = new SqlConnection();
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
con.Open();
SqlCommand command = new SqlCommand("spReport_SiteUsage_KP", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#fromDate", SqlDbType.DateTime));
command.Parameters.Add(new SqlParameter("#toDate", SqlDbType.DateTime));
command.Parameters[0].Value = Convert.ToDateTime(DatePicker1.SelectedDate.ToShortDateString());
command.Parameters[1].Value = DatePicker2.SelectedDate;
int i = command.ExecuteNonQuery();
con.Close();
Store Procedure :
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spReport_SiteUsage_KP]
#fromDate datetime = null,
#toDate datetime = null
AS
truncate table dbo.RPT_SiteUsage
IF (#FromDate is not null and #ToDate is not null) --Hourly Report, grouped by hour
Begin
insert into RPT_SiteUsage
select '' as ReportType,
'Site Usage for '+ datename(mm,#fromDate)+' '+datename(dd,#fromDate)+', '+datename(yy,#fromDate) +
' To '+datename(mm,#toDate)+' '+datename(dd,#toDate)+', '+datename(yy,#toDate) as ReportTitle,
min(#fromDate) as FromDate,max(#toDate) as ToDate,
isnull(count(s.SessionId),0) VisitsTotal,
isnull(count(distinct(s.cookieid)),0) VisitsUnique,
isnull(sum(PagesVisited),0) PageViews,
isnull(round(avg(convert(decimal(10,2),PagesVisited)),2),0) PagePerVisit,
isnull(min(PagesVisited),0) MinNoPageViews,
isnull(max(PagesVisited),0) MaxNoPageViews,
isnull(round(avg(convert(decimal(10,2),TimeInSiteMinutes)),2),0) AvgTimeInSite,
isnull(min(TimeInSiteMinutes),0) MinTimeSpent,
isnull(max(TimeInSiteMinutes),0) MaxTimeSpent,
isnull(sum(NewPeople),0) as NewVisitors
from
dbo.UMM_UserAction ua inner join dbo.UMM_Session s on ua.SessionId=s.Sessionid
left join
(select ua.sessionId, datediff(ss,min(Actiondate),max(Actiondate))/60 TimeInSiteMinutes
from dbo.UMM_UserAction ua
where ActionDate between #fromDate and #toDate
group by ua.sessionid
) sessionTime on ua.sessionId = sessionTime.sessionid
left join
(select ua.sessionId, 0 as NewPeople
from dbo.UMM_UserAction ua
inner join dbo.UMM_Session s on ua.SessionId=s.SessionId
inner join dbo.UMM_Cookie c on s.CookieId=c.CookieId
where ua.actiondate< #fromDate --this is the from date
group by UserId,ua.sessionId
) Old on ua.sessionId = Old.sessionid
left join
(select ua.sessionId,count(distinct(uaP.PageEntryId)) as PagesVisited
from dbo.UMM_UserAction ua,
dbo.UMM_UserActionPageReview uaP
where ua.UserActionId=uaP.UserActionId
and ActionDate between #fromDate and #toDate
group by ua.sessionId
)pVisited on ua.sessionId = pVisited.sessionId
where ActionDate between #fromDate and #toDate
IF (select count(*) from RPT_SiteUsage)=0
insert into RPT_SiteUsage
select '(1 day)' as ReportType,
'Site Usage for '+datename(mm,#fromDate)+' '+datename(dd,#fromDate)+', '+datename(yy,#fromDate) +
' To '+datename(mm,#toDate)+' '+datename(dd,#toDate)+', '+datename(yy,#toDate) as ReportTitle,
min(#fromDate) as FromDate,max(#toDate) as ToDate,
0 as VisitsTotal,
0 as VisitsUnique,
0 as PageViews,
0 as PagePerVisit,
0 as MinNoPageViews,
0 as MaxNoPageViews,
0 as AvgTimeInSite,
0 as MinTimeSpent,
0 as MaxTimeSpent,
0 as NewVisitors
END
Another idea, the TimeOut of each SqlCommand is also controlled individually, so, you can control it with CommandTimeOut property.
command.CommandTimeout = 120;
However, I would check the execution plan to see where is it wasting or hogging db resources, I suggest this just for experiment, not on production.
Well - I would say there's an error in your connection string. Please check it.
If it takes long before the query returns an error, there is probably something wrong with your connection (string).
It could be the fun issue with a bad query plan cached on the proc. Especially if the guts of the proc just as a Query in Query Analyzer runs fine. Check this link out on how to resolve the situation: http://www.mssqltips.com/tip.asp?tip=1304