JavaScript не может отправлять электронную почту из веб-браузера. Однако, отступив от решения, которое вы уже пытались реализовать, вы можете сделать то, что соответствует исходному требованию:
отправить сообщение без обновления страницы
blockquote>Вы можете использовать JavaScript для создания значений, которые будут нужны электронной почте, а затем сделать запрос AJAX к серверному ресурсу, который фактически отправит электронное письмо.
Если вы не знакомы с AJAX, быстрый поиск в Google даст вам информацию о том, какие серверные языки / технологии вы используете, так что ваша часть зависит от вас. много информации. Как правило, вы можете быстро запустить его и запустить с помощью функции $ .ajax () jQuery. Вам просто нужно иметь страницу на сервере, которая может быть вызвана в запросе.
В большинстве случаев лучше избегать скалярных функций, которые ссылаются на таблицы, потому что (как говорили другие) они в основном являются черными ящиками, которые нужно запускать один раз для каждой строки, и не могут быть оптимизированы механизм плана запросов. Поэтому они имеют тенденцию линейно масштабироваться, даже если у связанных таблиц есть индексы.
Возможно, вы захотите использовать встроенную табличную функцию, поскольку они оцениваются в соответствии с запросом и могут быть оптимизированы. Вы получаете желаемую инкапсуляцию, но производительность вставки выражений прямо в операторе select.
В качестве побочного эффекта от встраивания, они не могут содержать процедурный код (no Declare @variable; set @variable =. .; возвращение). Однако они могут возвращать несколько строк и столбцов.
Вы можете переписать свои функции примерно так:
create function usf_GIS_GET_LAT(
@City varchar (30),
@State char (2)
)
returns table
as return (
select top 1 lat
from GIS_Location with (nolock)
where [State] = @State
and [City] = @City
);
GO
create function usf_GIS_GET_LON (
@City varchar (30),
@State char (2)
)
returns table
as return (
select top 1 LON
from GIS_Location with (nolock)
where [State] = @State
and [City] = @City
);
Синтаксис их использования также немного отличается:
select
Lat.Lat,
Lon.Lon
from
Address_Location with (nolock)
cross apply dbo.usf_GIS_GET_LAT(City,[State]) AS Lat
cross apply dbo.usf_GIS_GET_LON(City,[State]) AS Lon
WHERE
ID IN (SELECT TOP 100 ID FROM Address_Location WITH(NOLOCK) ORDER BY ID DESC)
Они этого не делают.
В скалярных функциях нет ошибки, которая вызывала бы экспоненциальное снижение производительности в зависимости от количества строк, в которых выполняется скалярная функция. Попробуйте еще раз свои тесты и посмотрите на профилировщик SQL, взглянув на столбцы CPU и READS и DURATION. Увеличьте размер теста, включив в него тесты, которые занимают более секунды, две секунды и пять секунд.
CREATE FUNCTION dbo.slow
(
@ignore int
)
RETURNS INT
AS
BEGIN
DECLARE @slow INT
SET @slow = (select count(*) from sysobjects a
cross join sysobjects b
cross join sysobjects c
cross join sysobjects d
cross join sysobjects e
cross join sysobjects f
where a.id = @ignore)
RETURN @slow
END
go
SET STATISTICS TIME ON
select top 1 dbo.slow(id)
from sysobjects
go
select top 5 dbo.slow(id)
from sysobjects
go
select top 10 dbo.slow(id)
from sysobjects
go
select top 20 dbo.slow(id)
from sysobjects
go
select top 40 dbo.slow(id)
from sysobjects
SET STATISTICS TIME OFF
Выходные данные
SQL Server Execution Times:
CPU time = 203 ms, elapsed time = 202 ms.
SQL Server Execution Times:
CPU time = 889 ms, elapsed time = 939 ms.
SQL Server Execution Times:
CPU time = 1748 ms, elapsed time = 1855 ms.
SQL Server Execution Times:
CPU time = 3541 ms, elapsed time = 3696 ms.
SQL Server Execution Times:
CPU time = 7207 ms, elapsed time = 7392 ms.
Имейте в виду, что если вы запускаете скалярную функцию для строк в наборе результатов, скалярная функция будет выполняться для каждой строки без какой-либо глобальной оптимизации.
CREATE FUNCTION dbo.slow
(
@ignore int
)
RETURNS INT
AS
BEGIN
DECLARE @slow INT
SET @slow = (select count(*) from sysobjects a
cross join sysobjects b
cross join sysobjects c
cross join sysobjects d
cross join sysobjects e
cross join sysobjects f
where a.id = @ignore)
RETURN @slow
END
go
SET STATISTICS TIME ON
select top 1 dbo.slow(id)
from sysobjects
go
select top 5 dbo.slow(id)
from sysobjects
go
select top 10 dbo.slow(id)
from sysobjects
go
select top 20 dbo.slow(id)
from sysobjects
go
select top 40 dbo.slow(id)
from sysobjects
SET STATISTICS TIME OFF
Выходные данные
SQL Server Execution Times:
CPU time = 203 ms, elapsed time = 202 ms.
SQL Server Execution Times:
CPU time = 889 ms, elapsed time = 939 ms.
SQL Server Execution Times:
CPU time = 1748 ms, elapsed time = 1855 ms.
SQL Server Execution Times:
CPU time = 3541 ms, elapsed time = 3696 ms.
SQL Server Execution Times:
CPU time = 7207 ms, elapsed time = 7392 ms.
Имейте в виду, что если вы запускаете скалярную функцию для строк в наборе результатов, скалярная функция будет выполняться для каждой строки без какой-либо глобальной оптимизации.
CREATE FUNCTION dbo.slow
(
@ignore int
)
RETURNS INT
AS
BEGIN
DECLARE @slow INT
SET @slow = (select count(*) from sysobjects a
cross join sysobjects b
cross join sysobjects c
cross join sysobjects d
cross join sysobjects e
cross join sysobjects f
where a.id = @ignore)
RETURN @slow
END
go
SET STATISTICS TIME ON
select top 1 dbo.slow(id)
from sysobjects
go
select top 5 dbo.slow(id)
from sysobjects
go
select top 10 dbo.slow(id)
from sysobjects
go
select top 20 dbo.slow(id)
from sysobjects
go
select top 40 dbo.slow(id)
from sysobjects
SET STATISTICS TIME OFF
Выходные данные
SQL Server Execution Times:
CPU time = 203 ms, elapsed time = 202 ms.
SQL Server Execution Times:
CPU time = 889 ms, elapsed time = 939 ms.
SQL Server Execution Times:
CPU time = 1748 ms, elapsed time = 1855 ms.
SQL Server Execution Times:
CPU time = 3541 ms, elapsed time = 3696 ms.
SQL Server Execution Times:
CPU time = 7207 ms, elapsed time = 7392 ms.
Имейте в виду, что если вы запускаете скалярную функцию для строк в наборе результатов, скалярная функция будет выполняться для каждой строки без какой-либо глобальной оптимизации.
Simply put, because SQL expressions with user defined functions are less efficient than SQL expressions without them. The execution logic can't be optimized; and the function overhead (including calling protocols) must be incurred for every row.
KMike's advice is good. WHERE .. IN (SELECT something) is not likely to be an efficient pattern, and in this case can be easily replaced with a JOIN.
вы вызываете функцию два раза (два выбранных обращения к БД) для каждой строки в наборе результатов.
, чтобы ваш запрос быстрее соединялся с GIS_Location и пропускал функции:
SELECT
g.Lat,
g.Lon
FROM
Address_Location l WITH(NOLOCK)
INNER JOIN GIS_Location g WITH(NOLOCK) WHERE l.State = g.State AND l.City = g.City
WHERE
ID IN (SELECT TOP 100 ID FROM Address_Location WITH(NOLOCK) ORDER BY ID DESC)
Я не уверен, почему NOLOCK, или пункт о сумасшедшем, я просто скопировал вопрос ...
See if this works better... Or maybe a distinct inner join?
select a.*,
(select top 1 g.Lat from GIS_Location g where g.City = a.City and g.State = a.State) as Lat,
(select top 1 g.Lon from GIS_Location g where g.City = a.City and g.State = a.State) as Lon
from Address_Location a
where a.ID in (select top 100 ID from Address_Location order by ID desc)
As for the scalar function performance, I'm not sure.
Вы можете обернуть свою функциональность во встроенный TVF, это будет намного быстрее: