Conversion in SQL for secondary parameter - sql-server

I have the below sample table script:
create table #temp
(
field_01 int,
field_02 varchar(20)
)
insert into #temp
select
isnull(a.id,'UN'),
a.textcol
from
table1 a...
In the above table script, to insert value for field_01 should be either a.id(which is an int) or UN. Field_01 is integer and I'm confused about converting UN.
Getting conversion error:
Conversion failed when converting the varchar value 'UN' to data type int.
Should I convert the entire row or just UN part like isnull(a.id,CONVERT(INT, 'UN'))

If you just want to select the data you need to convert the whole ISNULL statement
select
convert(varchar,isnull(a.id,'UN')) as id,
a.textcol
from table1 a...
BUT if you want to insert it, then you can't. You have to change the DDL of the table in order to insert a varchar in an INT column. You have to change the column from INT to VARCHAR, otherwise it is impossible.
EDIT: To clarify as scsimon has said I'll add the complete query from the example given.
create table #temp
(
field_01 varchar(20),
field_02 varchar(20)
)
insert into #temp
select
id,
a.textcol
from table1 a...
select
isnull(field_01,'UN') as field_01,
field_02
from #temp

Related

SQL Server - How to enforce a field value from a combination of fields not repeated with another field value

I know I haven't framed the question very well, to be honest I found it difficult to explain without an example.
I have a table with SalesPersonID and SalesPersonSSN fields.
My requirement is a SalesPersonID should only exist with one SalesPersonSSN and vice versa.
If you see the table (sample data), the record with SalesPersonID 2003 is invalid because SalesPersonSSN 3344556677 already exists with SalesPersonID 2001. Similarly SalesPersonID 2001 should never exist with other than 3344556677.
I don't know how to enforce this rule in the table.
Also is there a simple query to find out if the rule is violated.
You want unique constraint :
alter table t
add constraint ssn unique(SalesPersonSSN);
If you want the data that violates the rules you can use exists :
select t.*
from table t
where exists (select 1
from table t1
where t1.SalesPersonSSN = t.SalesPersonSSN and
t1.SalesPersonID <> t.SalesPersonID
);
To find out if your rule is violated you could use the follwowing
Table
DECLARE #t TABLE (SalesPersonId INT, SalesPersonSSN VARCHAR(255))
INSERT INTO #t VALUES (2001,'3344556677'), (2002,'7755330099'), (2003,'3344556677')
Query
SELECT t.*
FROM #t t
INNER JOIN (SELECT SalesPersonSSN
FROM #t
GROUP BY SalesPersonSSN
HAVING COUNT(*) > 1
) a
ON a.SalesPersonSSN = t.SalesPersonSSN
You need to write the complete logic for it:
declare #ssn as varchar(255)='7755330099' --INPUT
declare #pid as int=201 --INPUT
declare #ssn1 as varchar(255)--local variable
declare #pid1 as int --local variable
select #pid1=SalesPersonId from #t where SalesPersonSSN=#ssn;
select #ssn1=SalesPersonSSN from #t where SalesPersonId=#pid;
if(#pid1 is not null and #pid1<>#pid)
begin
print('failed: as person '+cast(#pid1 as varchar(255))+' already asigned to ssn#'+#ssn)
end
if(#ssn1 is not null and #ssn1<>#ssn)
begin
print('failed: as ssn#'+#ssn1 +' already asigned to pid# '+cast(#pid as varchar(255)))
end
Table definition:
create TABLE #t(SalesPersonId INT, SalesPersonSSN VARCHAR(255))
INSERT INTO #t VALUES (2001,'3344556677'), (2002,'7755330099'), (2003,'3344556677')

SQL Query to Append Past Order with Most Recent Order

I have an order table that has both past membership data and current data. I want to view this data in single row. I have a temp table for past data, but not exactly sure how to write this query to get current data in the same row. I know it has something to do with the MAX(order no). Here is the query to get the past membership data in a temp table
set transaction isolation level read uncommitted
declare
#ship_master_customer_id varchar (10), #cycle_begin_date datetime, #cycle_end_date datetime, #OrderNo varchar(10), #Description Char(100)
create table #t1(ShipMasterCustomerID varchar(10), OrderNo varchar (10), cycle_begin_date datetime, cycle_end_date datetime, Description Char(100))
Insert into #t1
Select SHIP_MASTER_CUSTOMER_ID, ORDER_NO, CYCLE_BEGIN_DATE,CYCLE_END_DATE, DESCRIPTION FROM [ORDER_DETAIL]
where SHIP_MASTER_CUSTOMER_ID = '11115555' and
CYCLE_END_DATE = '2/29/2016'
Select * from #t1
Drop table #t1
Here is my script.
declare
#ship_master_customer_id varchar (10), #cycle_begin_date datetime, #cycle_end_date datetime, #OrderNo varchar(10), #Description Char(100)
create table #t2(ShipMasterCustomerID varchar(10), OrderNo varchar (10), cycle_begin_date datetime, cycle_end_date datetime, Description Char(100))
Insert into #t2 (shipmastercustomerid, orderno, cycle_begin_date, cycle_end_date, DESCRIPTION)
VALUES (1111555,9004731815, 2015/01/01, 2015/31/12,'Annual Mem'),
(1111555, 9005148308, 2016/01/01, 2016/31/12,'Annual Mem'),
(1111222, 9005027152, 2015/01/03, 2016/29/02,'Annual Mem'),
(1111222, 9005440369, 2016/01/03, 2017/31/03,'Annual Mem'),
(2223333, 9005027152, 2014/01/01, 2016/31/12,'Annual Mem'),
(2223333, 9005442116, 2016/01/01, 2017/31/12,'Annual Mem')
Select * from #t2
Drop table #t2
Sample Data
You don't need a temp table. You can query the same table twice, giving it an alias and then use the alias to prefix your column names. Since you didn't give us a complete schema or a fiddle I'm simulating your database with a temp table but the essence is here. There are considerations that you didn't mention, though. Are you guaranteed that every customer will have both a historical AND a current record? If not, they will not appear in the query below because of the INNER JOIN. You could change it to an OUTER join but when customers don't have a new record you will see NULL values in those columns. My point is that here be dragons... this is by no means a complete or bulletproof solution, only a nudge in the right direction.
DECLARE #ORDER_DETAIL AS TABLE(
ShipMasterCustomerId varchar(20),
OrderNo varchar(20),
cycle_begin_date date,
cycle_end_date date,
Description varchar(100)
)
INSERT #ORDER_DETAIL SELECT '11115555', '9005337015', '02/26/15', '2/29/16', 'Membership 26-Feb-2015 to 29-Feb-2016'
INSERT #ORDER_DETAIL SELECT '11115555', '9005743023', '02/28/17', '2/28/17', 'Membership 01-Mar-2016 to 28-Feb-2017'
SELECT
hist.ShipMasterCustomerId,
hist.OrderNo,
hist.cycle_begin_date,
hist.CYCLE_END_DATE,
hist.[Description],
curr.ShipMasterCustomerId,
curr.OrderNo,
curr.cycle_begin_date,
curr.CYCLE_END_DATE,
curr.[Description]
FROM
#ORDER_DETAIL AS hist
INNER JOIN #ORDER_DETAIL AS curr ON (
(curr.ShipMasterCustomerId = hist.ShipMasterCustomerId) AND (curr.cycle_end_date =
(SELECT MAX(cycle_end_date) FROM #ORDER_DETAIL WHERE ShipMasterCustomerId = hist.ShipMasterCustomerId))
)
WHERE
(hist.ShipMasterCustomerId = '11115555')
AND
(hist.cycle_end_date = '2/29/2016')

How to get the just inserted row in SQL Server stored procedure (without using trigger)?

I have stored procedures that inserts/updates records in some tables. Some columns of those tables have default values or auto-increment. Here's what I have:
ALTER PROCEDURE [dbo].[Usp___NewExpense]
#iCampaignID int,
#iCategory int,
#iUserID int,
#dDate Date,
#iAmountInINR int,
#strComments VarChar(200)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.Tbl_Expenses(iCampaignID, iCategory, dDate, iAmountInINR, strComments)
VALUES (#iCampaignID, #iCategory, #dDate, #iAmountInINR, #strComments);
-- How to get the record inserted using the above statement here without using triggers
-- or another select statement, so that I can assign values to the following variables?
Declare #justInsertedValue1 type1;
Declare #justInsertedValue2 type2;
Declare #justInsertedValue3 type3;
INSERT INTO dbo.Tbl_SomeOtherTable(col1, col2, col3)
VALUES (justInsertedValue1, justInsertedValue2, justInsertedValue3);
END
GO
Tbl_Expenses has about 9 columns in which two have default values and two have auto-increment set. How can I get the just inserted record just below my INSERT statement?
I know that I can use SCOPE_IDENTITY() and then a SELECT, but a query would probably make it inefficient (am I right?).
(By getting the just inserted record, I mean values of all fields of the just inserted record)
Edit: I haven't specified values for all the fields in my INSERT statement. I want to get those values inserted automatically by SQL Server due to DEFAULT/AUTO INCREMENT constraints also.
You can use the OUTPUT clause. You can even combine both inserts into one composite:
create table T1 (ID int IDENTITY(1,1) not null,ColA varchar(10) not null)
create table T2 (ID int IDENTITY(1,1) not null,T1ID int not null,ColB varchar(10) not null)
--Look ma! no local variables at all
insert into T2 (T1ID,ColB)
select t1.ID,'def'
from (
insert into T1(ColA)
output inserted.ID
values ('abc')
) t1
select * from T1
select * from T2
Results:
ID ColA
----------- ----------
1 abc
ID T1ID ColB
----------- ----------- ----------
1 1 def

Table variable error: Must declare the scalar variable "#temp"

I am trying to achieve:
declare #TEMP table (ID int, Name varchar(max))
insert into #temp SELECT ID, Name FROM Table
SELECT * FROM #TEMP
WHERE #TEMP.ID = 1 <--- ERROR AT #TEMP.ID
But I'm getting the following error:
Must declare the scalar variable "#temp".
What am I doing wrong?
A table alias cannot start with a #. So, give #Temp another alias (or leave out the two-part naming altogether):
SELECT *
FROM #TEMP t
WHERE t.ID = 1;
Also, a single equals sign is traditionally used in SQL for a comparison.
Either use an Allias in the table like T and use T.ID, or use just the column name.
declare #TEMP table (ID int, Name varchar(max))
insert into #temp SELECT ID, Name FROM Table
SELECT * FROM #TEMP
WHERE ID = 1
There is one another method of temp table
create table #TempTable (
ID int,
name varchar(max)
)
insert into #TempTable (ID,name)
Select ID,Name
from Table
SELECT *
FROM #TempTable
WHERE ID = 1
Make Sure You are selecting the right database.
If you bracket the # you can use it directly
declare #TEMP table (ID int, Name varchar(max))
insert into #temp values (1,'one'), (2,'two')
SELECT * FROM #TEMP
WHERE [#TEMP].[ID] = 1
You should use hash (#) tables, That you actually looking for because variables value will remain till that execution only.
e.g. -
declare #TEMP table (ID int, Name varchar(max))
insert into #temp SELECT ID, Name FROM Table
When above two and below two statements execute separately.
SELECT * FROM #TEMP
WHERE #TEMP.ID = 1
The error will show because the value of variable lost when you execute the batch of query second time.
It definitely gives o/p when you run an entire block of code.
The hash table is the best possible option for storing and retrieving the temporary value. It last long till the parent session is alive.
try the following query:
SELECT ID,
Name
INTO #tempTable
FROM Table
SELECT *
FROM #tempTable
WHERE ID = 1
It doesn't need to declare table.
You could stil use #TEMP if you quote the identifier "#TEMP":
declare #TEMP table (ID int, Name varchar(max));
insert into #temp SELECT 1 AS ID, 'a' Name;
SELECT * FROM #TEMP WHERE "#TEMP".ID = 1 ;
db<>fiddle demo
You've declared #TEMP but in your insert statement used #temp. Case sensitive variable names.
Change #temp to #TEMP

Use same GUID twice per row

I am building an application to transfer data from an SQL server to an offsite location via ftp and XML files.
I am building the XML data for each file via a query with FOR XML PATH('path'), TYPE.
I'm going to use a GUID to generate the filename as well as use as an identiifier within the file, currently my SQL to get the table is as follows (simplified):
SELECT LVL1.inv_account_no
, LVL1.cus_postcode
, CONVERT(varchar(255),NEWID()) + '.xml' as FileName
, (SELECT (SELECT CONVERT(varchar(255),NEWID()) FOR XML PATH('ident'), TYPE), (
SELECT.... [rest of very long nested select code for generating XML]
SQL Fiddle Example
This is giving me:
Account Postcode FileName xCol
AD0001 B30 3HX 2DF21466-2DA3-4D62-8B9B-FC3DF7BD1A00 <ident>656700EA-8FD5-4936-8172-0135DC49D200</ident>
AS0010 NN12 8TN 58339997-8271-4D8C-9C55-403DE98F06BE <ident>78F8078B-629E-4906-9C6B-2AE21782DC1D</ident>
Basically different GUID's for each row/use of NEWID().
Is there a way I can insert the same GUID into both columns without incrementing a cursor or doing two updates?
Try something like this:
SELECT GeneratedGuid, GeneratedGuid
FROM YourTable
LEFT JOIN (SELECT NEWID() AS GeneratedGuid) AS gg ON 1 = 1
"GeneratedGuid" has a different GUID for every row.
You could use a Common Table Expression to generate the NEWID for each resulting row.
Here is the SQL Fiddle : http://www.sqlfiddle.com/#!3/74c0c/1
CREATE TABLE TBL (
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
GCOL VARCHAR(255),
XCOL XML)
create table tbl2 (
id int identity(1,1) not null primary key,
foo int not null )
insert into tbl2 (foo) values
(10),(20),(30)
; WITH cte_a as ( select NEWID() as ID )
INSERT INTO TBL
SELECT CONVERT(varchar(255),cte_a.ID )
, (SELECT CONVERT(varchar(255),cte_a.ID) FOR XML PATH('Output'), TYPE)
from tbl2, cte_a
Create a temporary variable and assign a NEWID() to it. Then you can use this variable as many times in your SELECT or INSERT queries. Value of temporary variable remain same till it's scope. In following example #gid is a temporary variable and assigned a GUID value as VARCHAR(36)
DECLARE #gid varchar(36)
SET #gid = CAST(NEWID() AS VARCHAR(36))
INSERT INTO [tableName] (col1, col2) VALUES(#gid, #gid)
after executing the above query col1 and col2 from [tablename] will have same guid value.

Resources