Existe uma maneira de verificar se existe um índice em outro banco de dados?
AFAIK, as formas usuais ( sys.indexes
e INDEXPROPERTY
) são executadas apenas no contexto do banco de dados atual .
Existe uma maneira de verificar se existe um índice em outro banco de dados?
AFAIK, as formas usuais ( sys.indexes
e INDEXPROPERTY
) são executadas apenas no contexto do banco de dados atual .
Criei um job do SQL Server, no qual:
owner
do trabalhorun as
nenhuma etapa.O trabalho falhou com o erro:
'EXECUTE AS LOGIN' falhou para o login solicitado <my_username_here>
Quando mudei o nome owner
do trabalho para outro usuário com mais privilégios, o trabalho funcionou.
Portanto, parece que o trabalho é executado sob o usuário definido como owner
- mas li várias perguntas aqui ( 1 , 2 ) ou no SO discutindo "quem é o usuário que está executando o trabalho" e nenhuma mencionou isso.
Então eu me pergunto o que aconteceu no meu caso?
É possível restaurar os dados UTF8 de um nvarchar corrompido, que foi usado sem o N
prefixo?
Por exemplo, no snippet a seguir, gostaria @n1_fixed
de ter o valor correto com base em @n1
:
declare
@n1 nvarchar(10) = 'Ḿấxiḿứś',
@n2 nvarchar(10) = N'Ḿấxiḿứś';
declare
@n1_fixed nvarchar(10); -- somehow make it have the correct value, based on @n1
select iif(@n1_fixed = @n2, 1, 0)
Existe uma maneira inteligente de contar quantas variáveis equivalem a algum valor de destino (no SQL Server)?
Por exemplo, se eu tiver:
declare @a int = 1;
declare @b int = 2;
declare @c int = 1;
declare @target int = 1;
Então eu gostaria de fazer quantos @a, @b, @c
eqauls @target
.
Em linguagens imperativas, é fácil criar um array inline das variáveis e, em seguida, contá-las - por exemplo, em JS:
var a = 1, b = 2, c = 2, target = 1;
if ([a, b, c].filter(item => item == target).length == 1)
// do something
O equivalente em SQL dessa "matriz inline" seria uma tabela de coluna única, mas isso exigiria o uso DECLARE TABLE
de , o que eu gostaria de evitar.
Existe um método igualmente fácil para tal contagem em SQL?
Observe que estou menos interessado em "criar uma tabela sem declará-la" - o que realmente me importa é a contagem de variáveis em relação a uma variável de destino, portanto, se isso puder ser feito sem usar tabelas, seria melhor.
Qual é a diferença entre MERGE vs. MERGE INTO?
Quais são os casos de uso para cada um?
Surpreendentemente, não consegui encontrar nenhuma pergunta existente que pergunte sobre essa diferença.
A documentação para MERGE também não explica isso, e é usada apenas uma vez em um caso que não parece ser relevante para essa diferença (se houver).
Como uma WHERE
cláusula deve ser construída, de modo que:
Por exemplo, se tivermos este esquema:
CREATE TABLE Items
(
[Id] INT PRIMARY KEY,
[FirstDate] DATETIME,
[SecondDate] DATETIME
);
... com estes registros:
INSERT INTO Items ([Id], [FirstDate], [SecondDate])
VALUES
(1, '2021-1-1', '2022-1-1'),
(2, '2022-1-1', '2023-1-1'),
(3, '2022-1-1', '2024-1-1'),
(4, '2024-1-1', '2025-1-1'),
(5, '2024-1-1', '2026-6-1')
... então eu quero filtrar por FirstDate
e SecondDate
, de modo que:
FirstDate
e SecondDate
filtrar por 2022-1-1
, os registros 2 e 3 serão retornados ( mas não 1! ).FirstDate
e SecondDate
filtrar por 2024-1-1
, os registros 4 e 5 serão retornados ( mas não 3! ).FirstDate
e SecondDate
filtrar por 2025-1-1
, o registro 4 será retornado.Eu tenho um relacionamento de tabelas pai-filho e estava tentando obter cada linha pai com os detalhes mais recentes da linha filho.
Minhas tentativas de fazer isso usando uma subconsulta não funcionaram, e eu só consegui fazer isso usando um CTE.
gostaria de entender:
Aqui está um exemplo de brinquedo do relacionamento pai-filho ( demo completa está aqui ):
CREATE TABLE Cities
(
[Id] INT PRIMARY KEY,
[Name] NVARCHAR(100),
[EstablishedDate] DATETIME2 NULL,
);
CREATE TABLE Parks
(
[Id] INT PRIMARY KEY,
[Name] NVARCHAR(100),
[OpeningDate] DATETIME2 NULL,
[CityId] INT FOREIGN KEY REFERENCES Cities(Id)
);
Consulta bem-sucedida usando um CTE:
;WITH NumberedParks AS
(
SELECT *, ROW_NUMBER() OVER (PARTITiON BY CityId ORDER BY OpeningDate DESC) AS rownum
FROM Parks
)
SELECT *
FROM Cities
JOIN NumberedParks on Cities.Id = NumberedParks.CityId
WHERE rownum = 1;
Tentativas falhas:
SELECT *
FROM Cities
JOIN Parks on Cities.Id = Parks.CityId
WHERE EXISTS
(
SELECT TOP 1 Id
FROM Parks inner_parks
WHERE inner_parks.Id = Parks.Id
ORDER BY inner_parks.OpeningDate DESC
)
SELECT *
FROM Cities
JOIN Parks on Cities.Id = Parks.CityId
WHERE Parks.Id =
(
SELECT TOP 1 Id
FROM Parks inner_parks
WHERE inner_parks.Id = Parks.Id
ORDER BY inner_parks.OpeningDate DESC
);
No script a seguir ( veja uma demonstração completa aqui ):
SELECT *
FROM Table1
ORDER BY
CASE WHEN Field1 IS NOT NULL
THEN 0
END
0
?0
é interpretado? Não é o número ordinal das colunas na lista de seleção, porque a enumeração da lista de seleção começa com 1, não com 0. Então, o que é?Para elaborar um pouco, compare o trecho acima com o seguinte, que emite um erro:
SELECT *
FROM Table1
ORDER BY 0
A posição ORDER BY número 0 está fora do intervalo do número de itens na lista de seleção.
E também compare com o seguinte snippet, que emite outro erro:
SELECT *
FROM Table1
ORDER BY '0'
Uma expressão constante foi encontrada na lista ORDER BY, posição 1.
Parece que aninhar o 0
valor em uma case
cláusula faz com que funcione, mas não entendo por que e como?
Eu preciso de uma consulta simples, mas não consegui encontrar a maneira de fazê-lo:
Tenho uma tabela de serviços adquiridos por clientes, onde diferentes clientes podem adquirir o mesmo serviço (trivialmente), e cada cliente pode ter vários serviços ativos ou inativos:
ServiceId IsActive ServiceCustomerId
815 0 111
715 0 111
985 1 222
815 1 333
475 1 111
985 1 111
815 1 222
Eu quero obter registros de clientes que têm serviços ativos e inativos, então a saída seria ( ServiceId
pode ser omitida):
IsActive ServiceCustomerId
0 111
1 111
O que eu tenho é:
select ServiceCustomerId,IsActive from Services
group by ServiceCustomerId, IsActive
having count(IsActive) > 1
order by ServiceCustomerId
Que dá:
IsActive ServiceCustomerId
0 111
1 111
1 222
A demonstração pode ser vista aqui .
Como faço para filtrar apenas aqueles que têm os dois IsActive
grupos?
Eu quero usar a JSON_QUERY
com uma SELECT TOP 1
consulta de modo que o json resultante tenha esse registro top 1 em forma de objeto, em vez de em forma de tabela?
Por exemplo, a seguinte consulta ( demonstração ao vivo ):
CREATE TABLE Trees
(
[Id] INT,
[Type] NVARCHAR(100),
[Height] DECIMAL(2,1)
);
INSERT INTO Trees ([Id], [Type], [Height])
VALUES
(1, 'Palm', 5.5),
(2, 'Pine', 6.2),
(3, 'Apple', 2.5),
(4, 'Japanese Cedar', 0.5),
(5, 'Spanish Fir', 0.6);
SELECT
highestTree = JSON_QUERY(
(
SELECT TOP 1
Id as id,
Type as type,
Height as height
FROM Trees
WHERE Height = (SELECT Max(Height) FROM Trees)
FOR JSON PATH
)
),
lowestTree = JSON_QUERY(
(
SELECT TOP 1
Id as id,
Type as type,
Height as height
FROM Trees
WHERE Height = (SELECT MIN(Height) FROM Trees)
FOR JSON PATH
)
)
FOR JSON
PATH, WITHOUT_ARRAY_WRAPPER
;
saídas:
{"highestTree":[{"id":2,"type":"Pine","height":6.2}],"lowestTree":[{"id":4,"type":"Japanese Cedar","height":0.5}]}
Mas eu quero:
{"highestTree":{"id":2,"type":"Pine","height":6.2},"lowestTree":{"id":4,"type":"Japanese Cedar","height":0.5}}
Eu tenho o resultado de uma FOR JSON
expressão e gostaria de inseri-lo em uma coluna da tabela.
Como faço isso?
Aqui está uma das minhas tentativas malsucedidas (observe que a SELECT hightrees ... FOR JSON PATH
parte está correta, e pode ser vista na resposta à minha outra pergunta , e aqui também a demonstração ao vivo ), que dá o erro Invalid object name 'TreesJson'
:
SELECT * FROM (
SELECT
highTrees = JSON_QUERY(
(
SELECT
Id as id,
Type as type,
Height as height
FROM Trees WHERE [Height] > 5
FOR JSON PATH
)
),
lowTrees = JSON_QUERY(
(
SELECT
Id as id,
Type as type,
Height as height
FROM Trees WHERE [Height] < 1
FOR JSON PATH
)
)
FOR JSON
PATH, WITHOUT_ARRAY_WRAPPER
) AS TreesJson;
INSERT INTO TreesGrowthLog ([Day], [TreesGrowth])
VALUES (CAST(GETDATE() AS Date, (SELECT * FROM TreesJson FOR JSON AUTO))
Eu preciso construir um json com base nos resultados de duas consultas diferentes na mesma tabela, onde uma junção é irrelevante.
Considere o seguinte exemplo ( demo completa está aqui ):
CREATE TABLE Trees
(
[Id] INT,
[Type] NVARCHAR(100),
[Height] DECIMAL(2,1)
);
INSERT INTO Trees ([Id], [Type], [Height])
VALUES
(1, 'Palm', 5.5),
(2, 'Pine', 6.2),
(3, 'Apple', 2.5),
(4, 'Japanese Cedar', 0.5),
(5, 'Spanish Fir', 0.6);
Eu quero construir o seguinte json:
{
"highTrees":
[
{
"id": 1,
"type": "Palm",
"height": 5.5
},
{
"id": 1,
"type": "Pine",
"height": 6.2
}
],
"lowTrees":
[
{
"id": 4,
"type": "Japanese Cedar",
"height": 0.5
},
{
"id": 5,
"type": "Spanish Fir",
"height": 0.6
}
]
}
Eu tentei isso:
SELECT
Id as 'highTrees.id',
Type as 'highTrees.type',
Height as 'highTrees.height'
FROM Trees WHERE [Height] > 5
UNION ALL
SELECT
Id as 'lowTrees.id',
Type as 'lowTrees.type',
Height as 'lowTrees.height'
FROM Trees WHERE [Height] < 1
FOR JSON PATH;
Mas obviamente esse não é o caminho a seguir, pois fornece isso:
[
{
"highTrees": {
"id": 1,
"type": "Palm",
"height": 5.5
}
},
{
"highTrees": {
"id": 2,
"type": "Pine",
"height": 6.2
}
},
{
"highTrees": {
"id": 4,
"type": "Japanese Cedar",
"height": 0.5
}
},
{
"highTrees": {
"id": 5,
"type": "Spanish Fir",
"height": 0.6
}
}
]
Como posso alcançar o resultado desejado?
Eu tenho a seguinte tabela, onde [Data]
é do tipo nvarchar(max)
e seus valores são strings json válidas:
Identidade | Dados |
---|---|
1 |
{ "info" : { "done": true, "chosenOptions": ["one", "two"] } } |
2 |
{ "info" : { "done": true, "chosenOptions": ["one"] } } |
3 |
{ "info" : { "done": true, "chosenOptions": [] } } |
4 |
{ "info" : { "done": true } } |
Eu quero atualizar todas as linhas que Data
não incluem chosenOptions
, ou onde chosenOptions
é []
.
Data
valor json tenha várias outras propriedades além das mostradas aqui, se isso for importante.Minha consulta:
declare @defaultValue Nvarchar(100);
set @defaultValue = JSON_QUERY('["one", "two"]')
update myTable
set [Data] = JSON_QUERY(JSON_MODIFY([Data], '$.info.chosenOptions', @defaultValue))
where JSON_QUERY([data], '$.info.chosenOptions') IS NULL or
JSON_QUERY([data], '$.info.chosenOptions') = '[]'
O valor resultante chosenOptions
é uma string em vez de uma matriz (ignore o escape dos valores da matriz, isso é menos importante aqui):
Identidade | Dados |
---|---|
1 |
{ "info" : { "done": true, "chosenOptions": ["one", "two"] } } |
2 |
{ "info" : { "done": true, "chosenOptions": ["one"] } } |
3 |
{ "info" : { "done": true, "chosenOptions": "[\"one\", \"two\"]" } } <-- note que é uma string, não array |
4 |
{ "info" : { "done": true, "chosenOptions": "[\"one\", \"two\"]" } } <-- note que é uma string, não array |
Suponho que seja um comportamento esperado, mas como esse array pode ser atualizado corretamente?
Pelo que entendi da documentação , o operador Nested Loops é um operador de junção , ou seja, requer duas tabelas como entrada.
Se isso estiver correto, por que o operador Nested Loops é usado com uma entrada escalar ?
Por exemplo, pegue a seguinte consulta (do site de Paul White ) e seu plano de execução. Você pode ver que as entradas para o operador Nested Loops são (1) um Scalar e (2) uma tabela (o resultado do Index Seek).
Eu sei que um escalar não pode ser unido a uma tabela, então o que isso realmente significa? O que realmente está sendo unido?
USE AdventureWorks2019;
DECLARE @Like nvarchar(50) = N'D%';
SELECT p.[Name]
FROM Production.Product AS p
WHERE p.[Name] LIKE @Like;
BTW, presumo que seja uma pergunta bastante básica, mas não consegui encontrar um bom recurso que passe por esse básico metodologicamente, portanto, uma recomendação seria muito apreciada.
Estou aprendendo sobre planos de execução e tenho uma dúvida sobre a relação entre um Spool de Tabela e uma subconsulta correlacionada (estou seguindo este tutorial , não se importe com os erros de digitação).
Criei a seguinte tabela:
CREATE TABLE student (
ID INT IDENTITY(1, 1),
CX_Name VARCHAR(50),
CX_PhoneNum VARCHAR(50),
CX_Address VARCHAR(MAX),
CX_Credit INT
)
Em seguida, insira os valores:
INSERT INTO student
VALUES (
'Alen',
'9625788954',
'London',
500
)
GO 100
INSERT INTO student
VALUES (
'Frank',
'962445785',
'Germany',
1400
)
GO 100
Em seguida, executou a seguinte consulta, que inclui uma subconsulta correlacionada:
SELECT ID, CX_Name, CX_Credit
FROM student CX1
WHERE CX_Credit >= (
SELECT AVG(CX_Credit)
FROM student CX2
WHERE CX1.ID = CX2.ID
)
O plano de execução é:
O tutorial explica (o negrito é meu):
O SQL Server Engine lê os dados da tabela primeiro, classifica os dados antes de dividi-los em segmentos e, em seguida, cria uma tabela temporária para armazenar os grupos de dados .
Na outra parte do plano de explicação, o SQL Server Engine lê o Spool de Tabela e calcula o valor médio de crédito para cada grupo usando o operador Stream Aggregate.
O último operador Table Spool lerá os dados agrupados e os unirá para recuperar os valores superiores ao valor médio.
Os três operadores Table Spool usarão a mesma tabela temporária criada na primeira vez.
Eu não entendo a frase em negrito, de duas maneiras:
Eu tenho uma coluna (chamada RequestDate
) que preciso mudar de NULL
para NOT NULL
, mas há um índice clusterizado nessa coluna, então primeiro preciso descartar esse índice.
Originalmente, o índice foi criado usando:
CREATE CLUSTERED INDEX IX_RequestDate
ON [MyDB].[dbo].[MyTable] (RequestDate);
Para soltá-lo, executei:
Drop Index IX_RequestDate On [MyDB].[dbo].[MyTable]
E então tentei alterar a nulidade da coluna usando:
ALTER TABLE [MyDB].[dbo].[MyTable] ALTER COLUMN [RequestDate] DATETIME NOT NULL
Mas deu um erro:
O objeto 'MyTable' é dependente da coluna 'RequestDate'.
Em seguida, listei MyTable
os índices usando esta consulta e o índice ainda está lá, embora agora não tenha um nome e seu tipo seja HEAP
(originalmente CLUSTERED
):
TableName IndexName IndexType ColumnOrdinal ColumnName ColumnType
MyTable NULL HEAP 0 RequestDate datetime
Eu tenho 2 perguntas:
Observe que não há restrições nesta tabela.
Estou usando o SQL Server 2014, SO Windows Server 2012 R2, e o seguinte é a saída de SCRIPT TABLE AS -> CREATE TO
(alterei alguns dos nomes das colunas):
CREATE TABLE [dbo].[MyTable](
[RequestDate] [datetime] NULL,
[UserName] [nvarchar](50) NULL,
[HostName] [nvarchar](20) NULL,
[RequestContent] [ntext] NULL,
[ResponseContent] [ntext] NULL,
[RequestStatus] [int] NULL,
[ErrorMessage] [ntext] NULL,
[Duration] [float] NULL,
[ServiceName] [nvarchar](100) NULL,
[Direction] [int] NULL,
[RequestId] [uniqueidentifier] NOT NULL,
[IsRetry] [bit] NULL,
[CallerId] [nvarchar](100) NULL
)