I have function below but using it in a select and then inserting the value into temp table is too slow so I try to update to make better performance.
I think it's slow because it selects and then inserts into temp table. If I execute the script without function, it is fast, but I need it to use other place the same table.
CREATE FUNCTION [dbo].[FN_GET_CUSTOMER_INFO]
(#CUSTID VARCHAR(MAX))
RETURNS
#TBL TABLE (CUSTID VARCHAR(200),CUSTNAME NVARCHAR(200))
BEGIN
DECLARE #STATUS VARCHAR(200)
SELECT #STATUS = [STATUS]
FROM TBL_CUSTOMER
WHERE CUSTID = #CUSTID
IF #STATUS = 'INCLUDE'
BEGIN
INSERT INTO #TBL
SELECT *
FROM TBL_CUSTOMER
WHERE CUSTID = #CUSTID
END
ELSE
BEGIN
INSERT INTO #TBL
SELECT *
FROM TBL_CUSTOMER
WHERE CUSTID = #CUSTID
AND GENDER = 'M'
END
END
Related
I want to insert same record for status=0. But my logic is not working in MySQL.
Please add more text over here...
This question is about a stored procedure. And the user didn't provide any info what so ever.
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_insert2`(
IN P_page_Id int(11) ,
IN P_LanguageCode char,
IN P_page_status int(11),
IN p_created_by int(11),
IN p_created_date datetime,
OUT P_return int)
BEGIN
DECLARE v_isRecordExisting int;
DECLARE v_flags int;
SELECT
COUNT(*)
INTO
v_isRecordExisting
FROM
tbl_cms_pages_languages2
WHERE
page_status in(0,1)
AND
page_id = p_page_Id
AND
languagecode = P_LanguageCode;
IF
v_isRecordExisting = 0
THEN
INSERT INTO tbl_cms_pages_languages2 (
page_Id,
LanguageCode,
page_status,
created_by,
created_date
)
VALUES(
P_page_Id,
P_LanguageCode,
P_page_status,
P_created_by,
p_created_date
);
SET
p_return = 0;
ELSE
SET
p_return = 2;
END IF;
END
I have a Studentstatus table which gets a list of students from student table.
I made this procedure to update or create a new record, but I get the following error:
Procedure or function SaveAdvStudStata has too many arguments specified.
CREATE PROCEDURE [dbo].[SaveAdvStudStata]
#studentId int,
#stata int,
#description varchar(MAX),
#date DATE,
#issuedBy nvarchar(128)
AS
BEGIN
if exists (select StudentId
from dbo.StudentStata
where StudentId = #studentId
)
begin
Update dbo.StudentStata
set Stata = #stata
,Description = #description
,Date = #date
,IssuedBy = #issuedBy
where StudentId = #studentId
end
else
begin
Insert into dbo.StudentStata(StudentId
,Stata
,Description
,Date
,IssuedBy
)
VALUES (#studentId
,#stata
,#description
,#date
,#issuedBy
)
end
END
I am trying to implement an insert stored procedure. Basically, how it works is the stored procedure will check whether the record exists or not, then proceed to perform insert. A variable #status will be used as indicator. However, I found out a particular problem with this query is that when I execute the query, it will return the result #status = 1 no matter the data existed or not. However, the INSERT function is fine without any problems just the #status. The following is my implementation:
CREATE PROCEDURE save_proc
(
#userid varchar(10)
#name varchar(30)
)
AS
DECLARE #status int
if exists ( SELECT * FROM table1 where userID = #userid AND userName = #name)
SET #status = 0
else
INSERT INTO table1 (userID, userName) VALUES (#userid, #name)
SET #status = 1
SELECT #status
Try to put it in BEGIN END
CREATE PROCEDURE save_proc
(
#userid varchar(10)
#name varchar(30)
)
AS
DECLARE #status int
if exists ( SELECT * FROM table1 where userID = #userid AND userName = #name)
SET #status = 0
else
begin
INSERT INTO table1 (userID, userName) VALUES (#userid, #name)
SET #status = 1
end
If you are not putting the BEGIN END then the scope of your else statement is just the next line which is getting executed ie, INSERT INTO table1 (userID, userName) VALUES (#userid, #name) is only under the scope of else block. And SET #status = 1 is outside the scope of else block. So once the else block executes the next query will be executed which is SET #status = 1
On a side note:
When you are checking for if exists then don't use the * wildcard. Instead you can use 1 i.e,
if exists ( SELECT 1 FROM table1 where userID = #userid AND userName = #name)
else
begin
INSERT INTO table1 (userID, userName) VALUES (#userid, #name)
SET #status = 1
end
Modify code as above. You haven't defined scope of your else. It was upto insert statement only. SET #status = 1 was executed everytime
declare #RelevantMachines Table (MachineId int)
Select MachineId, ClusterId, MachineGuid, MachineName, RegisteredDate, MachineDetail, LastServiceCall, MachineType as MachineTypeId, ProductSetId
From PatchHub.Machine
Where ClusterId = #ClusterId
I would like to be able to return the select statement as a result set whilst at the same time populating the table variable with all of the returned rows MachineId values, this is in sql server 2008. How could you achieve this without running the select statement twice?
I don't believe you can do it in a single SELECT, I think the next best thing would be something like this:
declare #result table (
MachineId int,
ClusterId int,
MachineGuid guid,
MachineName varchar(100),
RegisteredDate datetime,
MachineDetail varchar(1000),
LastServiceCall int,
MachineType int,
ProductSetId int)
Select MachineId, ClusterId, MachineGuid, MachineName, RegisteredDate, MachineDetail, LastServiceCall, MachineType as MachineTypeId, ProductSetId
into #result
From PatchHub.Machine
Where ClusterId = #ClusterId
select * from #result
/* use #result table */
I have a userid table
UserId
JHOSMI
KALVIE
etc...
What I would like to do is create a select statement and pass user id, if the userid already exists then append 1 to the id, This gets complicated if you already have JHOSMI, JHOSMI1, then I want to return JHOSMI2.
Really appreciate help here.
Thanks in advance
edited 21-Jul
this is what i got so far.. but not working the way
select #p AS StaffID,
#old_p := #p,
#Cnt := #Cnt+1 As Lvl,
(SELECT #p :=Concat(#i, #Cnt)
FROM departmenttaff
WHERE upper(trim(UserId)) = upper(trim(StaffID))
AND upper(trim(department)) like upper(trim('SERVICE'))
) AS dummy
FROM (
SELECT
#i := upper(trim('JOHSMI')),
#p := upper(trim('JOHSMI')),
#old_p :='',
#Cnt:=0
) vars,
departmenttaff p
WHERE #p <> #old_p
order by Lvl Desc LIMIT 1;
This will do exactly what you want. You will need a unique constraint on your column.
You might also need to add in error code if success = 0.
This is in MSSQL, you will need to add the relevant commands for MySQL. I do not have MySQL so I cannot test it.
NOTE: You can replace the try catch with some IF EXISTS logic. I just prefer the try catch because its more stable for multiple threads.
begin tran
select * from #tmp
declare #success bit
declare #name varchar(50)
declare #newname varchar(50)
declare #nextid int
declare #attempts int
set #name = 'brad2something'
set #success = 0
set #attempts = 0
while #success = 0 and #attempts < 5 begin
begin try
set #attempts = #attempts + 1 -- failsafe
set #newname = #name
if exists (select * from #tmp where username = #name) begin
select #nextid = isnull(max(convert(int, substring(username, LEN(#name) + 1, 50))), 0) + 1
from #tmp where username like #name + '%' and isnumeric(substring(username, LEN(#name) + 1, 50)) = 1
set #newname = #name + CONVERT(varchar(20), #nextid)
end
insert into #tmp (username) values (#newname)
set #success = 1
end try begin catch end catch
end
--insert into #tmp (username)
--select
select #success
select * from #tmp
rollback
/*
drop table #tmp
create table #tmp (
username varchar(50) not null unique
)
insert into #tmp (username)
select 'brad'
union all select 'brad1'
union all select 'brad2something5'
union all select 'brad2'
union all select 'laney'
union all select 'laney500'
*/
I noticed you want to back fill data. If you want to back fill then this will work. It is extremely inefficient but there is no way around it. There is optimizing code you can put in for when an "error" occurs to prevent all previous counts from happening, but this will work.
begin tran
select * from #tmp
declare #success bit
declare #name varchar(50)
declare #newname varchar(50)
declare #nextid int
declare #attempts int
set #name = 'laney'
set #success = 0
set #attempts = 0
set #nextid = 1
while #success = 0 and #attempts < 5 begin
begin try
if exists (select * from #tmp where username = #name) begin
set #newname = #name + CONVERT(varchar(20), #nextid)
while exists (select * from #tmp where username = #newname) begin
set #nextid = #nextid + 1
set #newname = #name + CONVERT(varchar(20), #nextid)
end
end else
set #newname = #name
set #attempts = #attempts + 1 -- failsafe
insert into #tmp (username) values (#newname)
set #success = 1
end try begin catch end catch
end
--insert into #tmp (username)
--select
select #success
select * from #tmp
rollback
/*
drop table #tmp
create table #tmp (
username varchar(50) not null unique
)
insert into #tmp (username)
select 'brad'
union all select 'brad1'
union all select 'brad2something5'
union all select 'brad2'
union all select 'laney'
union all select 'laney500'
*/
Is it mandatory to have the count in same column? its better to have it in a different integer column. Anyways, if this is the requirement then select userid from table where userid like 'JHOSMI%', then do extract the number using mysql substr function.
For other people who might find this, here's a version in PostgreSQL:
create or replace function uniquify_username(varchar) returns varchar as $$
select $1 || coalesce((max(num) + 1)::varchar, '')
from
(select
substring(name, '^(.*?)[0-9]*$') as prefix,
coalesce(substring(name, '.*([0-9]+)$'), '0')::integer as num
from user1) users
where prefix = $1
$$ LANGUAGE sql;
I think it could be adapted to MySQL (though probably not as a stored procedure) but I don't have a MySQL server handy to do the conversion on.
Put a UNIQUE constraint on the column.
You didn't say what language you are using, so use this pseudo code
counter = 0
finished = false
while finished = false
{
try
{
if counter >= 1 then name = name + counter
counter = counter + 1
insert into table (name)
}
}
This code is extremely finicky. But will get the job done and there is no real other way to do this except for in sql, and you will always have some type of try catch to avoid two processes running at the same time. This way you use the unique key constraint to force the error, and supress it because it is expected.
I in no way condone using try/catch for business logic like this, but you are putting yourself in a situation thats unavoidable. I would say put the ID in a seperate column and make a unique constraint on both fields.
Proper solution:
Columns: Name, ID, Display Name
Unique constraint on: Name, ID
Display Name is a computed column (virtual) is Name + ID
If you do it this way, then all you have to do is INSERT INTO table (name, (select max() from table))