Я хотел бы получить что-то как следующий код, сгенерированный в JSTL
<c:choose>
<c:when test="${random number is even}">
<div class="redlogo">
</c:when>
<c:otherwise>
<div class="greenlogo">
</c:otherwise>
</c:choose>
Я не совсем уверен, но у меня складывается впечатление, что этот вопрос на самом деле об апсерте, который является следующей атомной операцией:
ОБНОВИТЬ
цель; ВСТАВИТЬ
строку в цель; DELETE
строка из целевого объекта. Разработчики-повернутые DBA часто наивно пишут это подряд:
-- For each row in source
IF EXISTS(<target_expression>)
IF @delete_flag = 1
DELETE <target_expression>
ELSE
UPDATE target
SET <target_columns> = <source_values>
WHERE <target_expression>
ELSE
INSERT target (<target_columns>)
VALUES (<source_values>)
Это просто худшее, что вы можете сделать, по нескольким причинам:
Это имеет расовое состояние. Строка может исчезнуть между IF EXISTS
и последующим DELETE
или UPDATE
.
Это расточительно. Для каждой транзакции выполняется дополнительная операция; может быть, это тривиально, но это полностью зависит от того, насколько хорошо вы проиндексировали.
Хуже всего - она следует итеративной модели, думая об этих проблемах на уровне одной строки. Это окажет наибольшее (наихудшее) влияние на общую производительность.
Одна очень незначительная (и я подчеркиваю, незначительная) оптимизация состоит в том, чтобы в любом случае просто попытаться ОБНОВИТЬ
; если строка не существует, @ @ ROWCOUNT
будет 0, и можно будет «безопасно» вставить:
-- For each row in source
BEGIN TRAN
UPDATE target
SET <target_columns> = <source_values>
WHERE <target_expression>
IF (@@ROWCOUNT = 0)
INSERT target (<target_columns>)
VALUES (<source_values>)
COMMIT
Худший случай, это все равно будет выполнять две операции для каждой транзакции, но, по крайней мере, есть шанс только делать один, и это также исключает гонку условие (вид).
Но реальная проблема заключается в том, что это все еще делается для каждой строки в источнике.
До SQL Server 2008 вам приходилось использовать неловкую 3-ступенчатую модель, чтобы справиться с этим на заданном уровне (все же лучше, чем рядно):
BEGIN TRAN
INSERT target (<target_columns>)
SELECT <source_columns> FROM source s
WHERE s.id NOT IN (SELECT id FROM target)
UPDATE t SET <target_columns> = <source_columns>
FROM target t
INNER JOIN source s ON t.d = s.id
DELETE t
FROM target t
WHERE t.id NOT IN (SELECT id FROM source)
COMMIT
Как я уже говорил, производительность была довольно паршивой, но все же намного лучше, чем подход «один ряд за один раз». SQL Server 2008, однако, наконец-то ввел синтаксис MERGE , так что теперь все, что вам нужно сделать:
MERGE target
USING source ON target.id = source.id
WHEN MATCHED THEN UPDATE <target_columns> = <source_columns>
WHEN NOT MATCHED THEN INSERT (<target_columns>) VALUES (<source_columns>)
WHEN NOT MATCHED BY SOURCE THEN DELETE;
Вот и все. Одно заявление. При использовании SQL Server 2008 и необходимости выполнения любой последовательности команд INSERT
, UPDATE
и DELETE
в зависимости от того, существует ли строка - , даже если это только одна строка , - нет оправдания не использовать MERGE
.
Можно даже OUTPUT
строк, на которые влияет MERGE
, в табличную переменную, если после этого необходимо выяснить, что было сделано. Простой, быстрый и безрисковый. Сделайте это.
это своего рода хитрость, если u получают информацию только о программном обеспечении; без идентификации пользователя, возможно, он может быть передан в порядке.
просто подумайте о google, я знаю, что он никогда не будет установлен в вашей системе, но хром снова является продуктом google, который, я полагаю, зонды и google ищет, чтобы дать соответствующую рекламу. Что такое чтение cookie, отличается ли это от чтения информации с вашего компьютера.
также я видел соответствующую рекламу, появляющуюся в почте yahoo, когда я ищу товары для покупок в Google. они наверняка читают некоторые сведения на вашем компьютере или в сеансе браузера.
Я думаю, что это нормально, чтобы отправить информацию из программного обеспечения, пока у вас нет пути идентифицировать от того, от какого пользователя он исходит.
-121--2093516-Этот немного уродлив, но работает...
<c:set var="rand"><%= java.lang.Math.round(java.lang.Math.random() * 2) %></c:set>
Позже можно проверить наличие $ {rand mod 2 = = 0}
и $ {rand mod 2 = = 1}
, чтобы получить нужный результат.
Надеюсь, это поможет! random taglib
Также вы можете попробовать функцию $ Math.random .
Вы можете обернуть java.util.Random
в bean-компонент и использовать jsp: useBean
.
package com.example;
import java.util.Random;
public class RandomBean {
private static final Random RANDOM = new Random();
public int getNextInt() {
return RANDOM.nextInt();
}
}
... чтобы вы могли использовать его в JSP следующим образом:
<jsp:useBean id="random" class="com.example.RandomBean" scope="application" />
...
<div class="${random.nextInt % 2 == 0 ? 'redlogo' : 'greenlogo'}">
(обратите внимание, что я оптимизировал c: select
с помощью тернарного оператора).