i have declared a variable #S and i am storing a sub query value in it which is returning more than one record , now what i want is to use it in a select statement , can i do that is it possible,
here is my query what i was trying but getting an error Must declare the scalar variable "#S"
Declare #S AS NVarchar(MAX)
SET #S = '(SELECT es.FirstName FROM [User] es WHERE es.UserId IN (SELECT CustomerUserID FROM OrderInfo))'
SELECT
OrderInfoId,
BorrowerFirstName As ConsumerFirstName,
BorrowerLastName As ConsumerLastName,
RequestedURL,
Requests,
SELECT #S,
u.FirstName +'' ''+ u.LastName As Affiliate,
o.RequestDateTime As DateOfTransaction,
o.RequestIPAddress As OriginatingIPAddress,
o.Requests As Status
from orderInfo o
inner join [User] u on o.AffiliateId = u.UserId
is it possible to do that. any help will be appreciated
If you want to append as a single string the result of the sub-query to every row produced by the main query, then, first of all you have to initialize #S:
Declare #S AS NVarchar(MAX) = ''
then properly set it:
SELECT #S = #S + ' ' + es.FirstName
FROM [User] es
WHERE es.UserId IN (SELECT CustomerUserID FROM OrderInfo)
and finally consume its contents in the main query:
SELECT
OrderInfoId,
BorrowerFirstName As ConsumerFirstName,
BorrowerLastName As ConsumerLastName,
RequestedURL,
Requests,
(SELECT #S),
u.FirstName +'' ''+ u.LastName As Affiliate,
o.RequestDateTime As DateOfTransaction,
o.RequestIPAddress As OriginatingIPAddress,
o.Requests As Status
from orderInfo o
inner join [User] u on o.AffiliateId = u.UserId
Your biggest issue is that you're trying to select multiple rows into a single column. This can't be done. You will need to concatenate the FirstNames into a single value. There are a few ways to do this. One popular way is to use STUFF with FOR XML This is an example of how you would get all of the FirstNames that match your sub query into a column. The names will be comma separated.
SELECT
OrderInfoId,
BorrowerFirstName AS ConsumerFirstName,
BorrowerLastName AS ConsumerLastName,
RequestedURL,
Requests,
STUFF((SELECT
', ' + es.FirstName
FROM
[User] es
WHERE
es.UserId IN (SELECT
CustomerUserID
FROM
OrderInfo)
ORDER BY
es.FirstName
FOR
XML PATH('')
),1,2,'') AS CustomerFirstNames,
u.FirstName + ' ' + u.LastName AS Affiliate,
o.RequestDateTime AS DateOfTransaction,
o.RequestIPAddress AS OriginatingIPAddress,
o.Requests AS Status
FROM
orderInfo o
INNER JOIN [User] u ON o.AffiliateId = u.UserId
This seems a little strange too considering you're going to get ALL user first names that have a CustomerID in orderInfo. You might want to filter your sub query by orderInfo.Id or something.
Are you sure you're not just trying to get the CustomerID first name? You can join to [User] again to get this information.
SELECT
OrderInfoId,
BorrowerFirstName AS ConsumerFirstName,
BorrowerLastName AS ConsumerLastName,
RequestedURL,
Requests,
cu.FirstName AS Customer,
u.FirstName + ' ' + u.LastName AS Affiliate,
o.RequestDateTime AS DateOfTransaction,
o.RequestIPAddress AS OriginatingIPAddress,
o.Requests AS Status
FROM
orderInfo o
INNER JOIN [User] u ON o.AffiliateId = u.UserId
INNER JOIN [User] cu ON o.CustomerUserID = cu.UserId
you need to make the entire sql statement a string, and use sp_executesql like so:
DECLARE #OrderID int;
SET #ParmDefinition = N'#SubQuery varchar(255), '+
'#OrderInfoOUT varchar(30) OUTPUT';
SET #S = '(SELECT es.FirstName FROM [User] es WHERE es.UserId IN (SELECT CustomerUserID FROM #OrderInfoOUT = OrderInfo))';
SET #SQL =' OrderInfoId, '+
'BorrowerFirstName As ConsumerFirstName, '+
'BorrowerLastName As ConsumerLastName, '+
'RequestedURL, '+
'Requests, '+
#SubQuery+', '+
'u.FirstName +''' '''+ u.LastName As Affiliate, '+
'o.RequestDateTime As DateOfTransaction, '+
'o.RequestIPAddress As OriginatingIPAddress, '+
'o.Requests As Status'+
'from orderInfo o '+
'inner join [User] u on o.AffiliateId = u.UserId';
sp_executesql #SQL, #ParmDefinition, #SubQuery=#S, #OrderIDOUT=OrderID OUTPUT;
Then you can store the results in variables as I've show with OrderInfoOUT
You won't be able to run it this way. You would need something like sp_executesql
I believe there is a mix of concepts in your question: dynamic SQL with table variables.
If you're using SQL Server 2008 or uper, you have a choice to create table variables that keep alives for the period the hosting routine is running.
You can define something similar to this:
DECLARE #UserInfo TABLE
(
FirstName varchar(50) NOT NULL
);
Load the information as follows:
INSERT #UserInfo
SELECT es.FirstName
FROM [User] es
WHERE es.UserId IN (SELECT CustomerUserID FROM OrderInfo)
Finally you can join table variables similar as temporal tables based on your needs.
Related
Today I have this query that returns all rows from all tables. But now I want to add a new column that would be the number of records in the last year. Most tables have a column called "DateInsert".
I have this:
SELECT
SCHEMA_NAME(t.[schema_id]) AS [SCHEMA],
OBJECT_NAME(p.[object_id]) AS [NOME_TABELA],
SUM(p.[rows]) AS [ROW_COUNT]
FROM [sys].[partitions] p
INNER JOIN [sys].[tables](NOLOCK) t ON p.[object_id] = t.[object_id]
WHERE p.[index_id] < 2
GROUP BY p.[object_id]
,t.[schema_id]
ORDER BY [ROW_COUNT] desc
How do i add a new column counting rows from the last year only?
Assuming, each table has DateInsert column. You can try using Dynamic SQL to prepare the count for each table from last year in one temporary table and then you can Join that temp table with your final query.
Something like this
Please note that, if any of your table dont have DateInsert Column, this query will fail. In order to look at list of tables, you can prepare the dynamic SQL for those tables only
DECLARE #SQLQuery NVARCHAR(MAX)
-- Preparing Dynamic SQL
SELECT #SQLQuery = STUFF(
(SELECT CONCAT('UNION SELECT ''', name ,''' AS [TableName], COUNT(1) AS [NoOfRowsFromLastYear] FROM ['
, name
, '] WITH (NOLOCK) WHERE YEAR(DateInsert) = (YEAR(GETDATE())-1)')
FROM [sys].[tables]
--WHERE name in ('TableName')
FOR XML PATH(''))
, 1, LEN('UNION '), ''
)
SELECT #SQLQuery = CONCAT('SELECT * INTO ##TableDetail FROM (', #SQLQuery, ') DataSet')
-- Check for table, if available, drop it
IF OBJECT_ID('tempdb..##TableDetail') IS NOT NULL DROP TABLE ##TableDetail;
-- Execute prepared query
EXECUTE sp_executesql #SQLQuery
-- Final Query with [ROW_COUNT_FROM_LAST_YEAR]
SELECT
SCHEMA_NAME(t.[schema_id]) AS [SCHEMA],
OBJECT_NAME(p.[object_id]) AS [NOME_TABELA],
SUM(p.[rows]) AS [ROW_COUNT],
td.NoOfRowsFromLastYear AS [ROW_COUNT_FROM_LAST_YEAR]
FROM [sys].[partitions] p
INNER JOIN [sys].[tables](NOLOCK) t ON p.[object_id] = t.[object_id]
INNER JOIN ##TableDetail td ON td.[TableName] = t.name
WHERE p.[index_id] < 2
GROUP BY p.[object_id]
,t.[schema_id]
,td.NoOfRowsFromLastYear
ORDER BY [ROW_COUNT] desc
I've never used XML before. I have the following queries - that need to be output into XML file in a particular format
---- Show Server details
GO
SELECT
##servername as ServerName,
##version as Environment,
SERVERPROPERTY('productversion'),
SERVERPROPERTY ('InstanceName')
-- Show DB details
SELECT
name AS DBName ,
Collation_name as Collation,
User_access_Desc as UserAccess,
Compatibility_level AS CompatiblityLevel ,
state_desc as Status,
Recovery_model_desc as RecoveryModel
FROM sys.databases
ORDER BY Name
-- Sysadmin Roles
SELECT
p.name AS [Name],
r.type_desc,
r.is_disabled,
r.default_database_name
FROM
sys.server_principals r
INNER JOIN
sys.server_role_members m ON r.principal_id = m.role_principal_id
INNER JOIN
sys.server_principals p ON p.principal_id = m.member_principal_id
WHERE
r.type = 'R' and r.name = N'sysadmin'
-- Find all users associated with a database
DECLARE #DB_USers TABLE
(DBName sysname, UserName varchar(max), LoginType sysname, AssociatedRole varchar(max))--,create_date datetime,modify_date datetime)
INSERT #DB_USers
EXEC sp_MSforeachdb
use [?]
SELECT ''?'' AS DB_Name,
case prin.name when ''dbo'' then prin.name + '' (''+ (select SUSER_SNAME(owner_sid) from master.sys.databases where name =''?'') + '')'' else prin.name end AS UserName,
prin.type_desc AS LoginType,
isnull(USER_NAME(mem.role_principal_id),'''') AS AssociatedRole
FROM sys.database_principals prin
LEFT OUTER JOIN sys.database_role_members mem ON prin.principal_id=mem.member_principal_id
WHERE prin.sid IS NOT NULL and prin.sid NOT IN (0x00) and
prin.is_fixed_role <> 1 AND prin.name NOT LIKE ''##%'''
SELECT
DBName,UserName ,LoginType ,
STUFF(
(
SELECT ',' + CONVERT(VARCHAR(500), AssociatedRole)
FROM #DB_USers user2
WHERE
user1.DBName=user2.DBName AND user1.UserName=user2.UserName
FOR XML PATH('')
)
,1,1,'') AS Permissions_user
FROM #DB_USers user1
GROUP BY
DBName,UserName ,LoginType --,create_date ,modify_date
ORDER BY DBName,UserName
--List of all the jobs currently running on server
SELECT
job.job_id,
notify_level_email,
name,
enabled,
description,
step_name,
command,
server,
database_name
FROM
msdb.dbo.sysjobs job
INNER JOIN
msdb.dbo.sysjobsteps steps
ON
job.job_id = steps.job_id
-- Show details of extended stored procedures
SELECT * FROM master.sys.extended_procedures
I don't know where to start
I have the following SQL statement so that I can script out view creation using if not exists with sp_executesql but the statement is giving me errors due to the single quotes around 1 in my last where statement. Is there any way around this?
IF NOT EXISTS (SELECT * FROM SYS.objects WHERE NAME = 'vw_JeopardyAlertDetails' AND TYPE = 'V')
EXEC sp_executesql #statement = N'CREATE VIEW [dbo].[vw_JeopardyAlertDetails]
AS
SELECT Main.TicketNumber, TS.TicketStateDesc, Main.ApptEnd, ISNULL(C.FirstName, '') AS FirstName, ISNULL(C.LastName, '') AS LastName, ISNULL(Main.CustomerID, '')
AS CustomerID, Main.ApptID, Main.ID, Main.TicketType
FROM (SELECT s.TicketState, s.TicketID AS ID, s.ApptEnd, dbo.Ticket.TicketNumber, dbo.Ticket.TimeOpened, dbo.Ticket.CreatedBy, dbo.Ticket.ReportedBy,
dbo.Ticket.ModifiedBy, dbo.Ticket.ChangedBy, dbo.Ticket.Priority, dbo.Ticket.ServingArea, dbo.Ticket.StructureLink, dbo.Ticket.CustomerID,
dbo.Ticket.TicketCategory, dbo.Ticket.TicketCode, s.ApptStart, s.TicketType, s.CanReschedule, ISNULL(s.ID, 0) AS ApptID
FROM dbo.Schedule AS s INNER JOIN
dbo.Ticket ON s.TicketID = dbo.Ticket.ID
WHERE (s.TicketState IN
(SELECT DISTINCT TicketState
FROM dbo.AlertJeopardyTicketState
WHERE (IsJeopardyState = '1'))) AND (s.ApptEnd >= CONVERT(DATETIME, CONVERT(VARCHAR(10), GETDATE(), 111) + ' ' + dbo.GetJeopardyStartTime()))
AND (s.ApptEnd <= GETDATE())) AS Main LEFT OUTER JOIN
dbo.Customer AS C ON Main.CustomerID = C.ID LEFT OUTER JOIN
dbo.TicketStatus AS TS ON Main.TicketState = TS.ID
GO' ;
ELSE PRINT N'vw_JeopardyAlertDetails ALREADY EXISTS'
GO
You'll need to double up those quotes in your Sql #statement, e.g.
ISNULL(C.FirstName, '')
needs to be
ISNULL(C.FirstName, '''')
Simplified fiddle here
I am trying to execute the following dynamic query but I got an error: Invalid column name 'cat'
DECLARE #SQLDelQuery AS NVARCHAR(1200)
DECLARE #MemberNames varchar(50)
SET #MemberNames = 'cat'
SET #SQLDelQuery = 'SELECT [Email] FROM [aspnet_Membership] am
INNER JOIN [aspnet_Users] u
ON (am.UserId = u.UserId)
INNER JOIN [Member] m
ON (am.UserId = m.UserId)
WHERE u.UserName IN (' + #MemberNames + ')
EXECUTE(#SQLDelQuery)
If I change it to the normal query I am fine:
SELECT [Email] FROM [aspnet_Membership] am
INNER JOIN [aspnet_Users] u
ON (am.UserId = u.UserId)
INNER JOIN [Member] m
ON (am.UserId = m.UserId)
WHERE u.UserName IN ('cat')
Anyone can point out my error? Thanks.
Since cat is a varchar you need to include single quotes around it and you need to place the closing parentheses for the IN clause inside of the sql string.
The new code will be:
DECLARE #SQLDelQuery AS NVARCHAR(1200)
DECLARE #MemberNames varchar(50)
SET #MemberNames = 'cat'
SET #SQLDelQuery = 'SELECT [Email] FROM [aspnet_Membership] am
INNER JOIN [aspnet_Users] u
ON (am.UserId = u.UserId)
INNER JOIN [Member] m
ON (am.UserId = m.UserId)
WHERE u.UserName IN (''' + #MemberNames + ''')'
EXECUTE(#SQLDelQuery)
See a SQL Fiddle Demo with the query string printed. This generates a query string like this:
SELECT [Email]
FROM [aspnet_Membership] am
INNER JOIN [aspnet_Users] u
ON (am.UserId = u.UserId)
INNER JOIN [Member] m
ON (am.UserId = m.UserId)
WHERE u.UserName IN ('cat') -- cat surrounded in single quotes
You need to pass it as a string to the dynamic query
SET #MemberNames = '''cat'''
Difference in the resulted query is
WHERE u.UserName IN (cat) -- cat is taking as a column name here
WHERE u.UserName IN ('cat') -- cat is taking as a string here
Your string:
WHERE u.UserName IN (' + #MemberNames + ')
will evaluate to:
WHERE u.UserName IN (cat)
because the apostrophes you have are just encapsulating the string, and there are no extra apostrophes around the string literal.
You need:
WHERE u.UserName IN (''' + #MemberNames + ''')
Alternately, you can leave your query as is, and seperate each ID with apostrophes in your #MemberNames variable:
SET #MemberName = '''cat''' -- for a single user
SET #MemberName = '''cat'', ''dog''' -- for multiple users
Your dynamic query uses ' characters as the string delimiter, so the last line ends up reading like this after the string is built:
WHERE u.UserName IN (cat)
According to this, cat reads like a column name.
To fix it, you need to include escaped ' characters in either the definition of
`SET #MemberNames = '''cat'''`
or in the string being used to build the sql:
`WHERE u.UserName IN (''' + #MemberNames + ''')'`
This is for SS 2005.
Why I am i only getting 4000 characters and not 8000?
It truncates the string #SQL1 at 4000.
ALTER PROCEDURE sp_AlloctionReport(
#where NVARCHAR(1000),
#alldate NVARCHAR(200),
#alldateprevweek NVARCHAR(200))
AS
DECLARE #SQL1 NVARCHAR(Max)
SET #SQL1 = 'SELECT DISTINCT VenueInfo.VenueID, VenueInfo.VenueName, VenuePanels.PanelID,
VenueInfo.CompanyName, VenuePanels.ProductCode, VenuePanels.MF, VenueInfo.Address1,
VenueInfo.Address2, '' As AllocationDate, '' As AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName,
VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName,
VenueCategories.Category, VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment,
[VenueCategories].[Category] + '' Allocations'' AS ReportHeader,
ljs.AbbreviationCode AS PrevWeekCampaign
FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID)
INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID)
LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
WHERE ' + #alldateprevweek + ') ljs
ON VenuePanels.PanelID = ljs.PanelID)
INNER JOIN (SELECT VenueInfo.VenueID, VenuePanels.PanelID, VenueInfo.VenueName, VenueInfo.CompanyName, VenuePanels.ProductCode,
VenuePanels.MF, VenueInfo.Address1, VenueInfo.Address2, CampaignAllocations.AllocationDate,
CampaignProductions.AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName,
VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName, VenueCategories.Category,
VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment, [Category] + '' Allocations'' AS ReportHeader,
ljs2.AbbreviationCode AS PrevWeekCampaign
FROM ((((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID)
INNER JOIN CampaignAllocations ON VenuePanels.PanelID = CampaignAllocations.PanelID)
INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID = CampaignProductions.CampaignID)
INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID)
LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
WHERE ' + #alldateprevweek + ') ljs2
ON VenuePanels.PanelID = ljs2.PanelID
WHERE ' + #alldate + ' AND ' + #where + ') ljs3
ON VenueInfo.VenueID = ljs3.VenueID
WHERE (((VenuePanels.PanelID)<>ljs3.[PanelID] And
(VenuePanels.PanelID) Not In (SELECT PanelID FROM CampaignAllocations WHERE ' + #alldateprevweek + '))
AND ' + #where + ')
UNION ALL
SELECT VenueInfo.VenueID, VenueInfo.VenueName, VenuePanels.PanelID, VenueInfo.CompanyName, VenuePanels.ProductCode,
VenuePanels.MF, VenueInfo.Address1, VenueInfo.Address2, CampaignAllocations.AllocationDate,
CampaignProductions.AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName,
VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName, VenueCategories.Category,
VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment, [Category] + '' Allocations'' AS ReportHeader,
ljs.AbbreviationCode AS PrevWeekCampaign
FROM ((((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID)
INNER JOIN CampaignAllocations ON VenuePanels.PanelID = CampaignAllocations.PanelID)
INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID = CampaignProductions.CampaignID)
INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID)
LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
WHERE ' + #alldateprevweek + ') ljs
ON VenuePanels.PanelID = ljs.PanelID
WHERE ' + #alldate + ' AND ' + #where
Select #SQL1
You have declared this as nvarchar(max) which allows 2GB of data so it will store 2GB.
What is happening:
The datatype is not yet nvarchar(max) until assignment to #sql1
Before that, it's a collection of strings, each less than 4000 (constants)
You are concatenating short constants with short variables (short = < 4000)
So you have 4000 characters put into #sql1
So, you have make sure you have nvarchar(max) on the right hand side.
One idea. The 2nd line concatenates nvarchar(max) with a constant = nvarchar(max)
SET #SQL1 = ''
SET #SQL1 = #SQL1 + 'SELECT DISTINCT Venue...
....
It's no different to the integer division that happens in every langauge.
declare #myvar float
set #myvar = 1/2 --gives zero because it's integer on the right
Operator precedence (infers datatype precedence) is always "assignment" last... why should unicode strings in SQL Server be any different?
Update: gbn's answer is right, and I was wrong. As MSDN points out, nvarchar(max) supports up to 2^31-1 bytes of data, stored as UCS-2 (2 bytes per character, plus 2 for BOM). Your problem seems to be with string concatenation, not data type limits.
That said, if you're using it to build a SQL string, why not use VARCHAR? Do you have field names that aren't representable by the database's native character set (usually Latin-1)?
Finally -- you could simplify your entire problem by just not using dynamic SQL in your stored procedure. Create some table-valued functions that take your where-clause strings and return tables, and then just JOIN them in your procedure. As a bonus it will almost certainly be much faster, since at very least the database will be able to cache the SP body as a prepared statement.
i resolve problem
just include N character before every string and problem solved
for example
declare #sql nvarchar(max) = '' + #Where + 'SomeThing';
must be
declare #sql nvarchar(max) = N'' + #Where + N'SomeThing';
if you set string to empty also must set N''
if #where is null
set #where = N''
:-) simple answer