Вот более общий способ, который немного чище:
Создайте свою форму как это (может быть фиктивная форма, которая ничего не делает):
<form class="validateDontSubmit">
...
Привязать все формы, которые вы действительно не хотите подавать:
$(document).on('submit','.validateDontSubmit',function (e) {
//prevent the form from doing a submit
e.preventDefault();
return false;
})
Теперь скажем, что у вас есть <a>
(в пределах <form>
), что при нажатии вы хотите проверить форму:
$('#myLink').click(function(e){
//Leverage the HTML5 validation w/ ajax. Have to submit to get em. Wont actually submit cuz form
//has .validateDontSubmit class
var $theForm = $(this).closest('form');
//Some browsers don't implement checkValidity
if (( typeof($theForm[0].checkValidity) == "function" ) && !$theForm[0].checkValidity()) {
return;
}
//if you've gotten here - play on playa'
});
Немногие примечания здесь:
checkValidity()
(по крайней мере, в хром). Если другие могут добавлять комментарии при тестировании этой теории в других браузерах, я обновлю этот ответ. <form>
. Это был просто чистый и гибкий способ решения общего назначения. На SQL Server 2005 можно использовать CTEs (Общие Выражения Таблицы) :
with Hierachy(CustomerID, ParentID, Name, Level)
as
(
select CustomerID, ParentID, Name, 0 as Level
from Customers c
where c.CustomerID = 2 -- insert parameter here
union all
select c.CustomerID, c.ParentID, c.Name, ch.Level + 1
from Customers c
inner join Hierachy ch
on c.ParentId = ch.CustomerID
)
select CustomerID, ParentID, Name
from Hierachy
where Level > 0
Вы не можете сделать рекурсии в SQL без хранимых процедур. Способ решить это использует Вложенные Наборы, они в основном моделируют дерево в SQL как набор.
Уведомление, что это потребует изменения в текущей модели данных или возможно выясняющий, как создать представление об исходной модели.
пример Postgresql (использующий очень немного postgresql расширений, просто ПОСЛЕДОВАТЕЛЬНЫХ и НА ОТБРАСЫВАНИИ ФИКСАЦИИ, большая часть RDBMSes будет иметь схожую функциональность):
Установка:
CREATE TABLE objects(
id SERIAL PRIMARY KEY,
name TEXT,
lft INT,
rgt INT
);
INSERT INTO objects(name, lft, rgt) VALUES('The root of the tree', 1, 2);
Добавление ребенка:
START TRANSACTION;
-- postgresql doesn't support variables so we create a temporary table that
-- gets deleted after the transaction has finished.
CREATE TEMP TABLE left_tmp(
lft INT
) ON COMMIT DROP; -- not standard sql
-- store the left of the parent for later use
INSERT INTO left_tmp (lft) VALUES((SELECT lft FROM objects WHERE name = 'The parent of the newly inserted node'));
-- move all the children already in the set to the right
-- to make room for the new child
UPDATE objects SET rgt = rgt + 2 WHERE rgt > (SELECT lft FROM left_tmp LIMIT 1);
UPDATE objects SET lft = lft + 2 WHERE lft > (SELECT lft FROM left_tmp LIMIT 1);
-- insert the new child
INSERT INTO objects(name, lft, rgt) VALUES(
'The name of the newly inserted node',
(SELECT lft + 1 FROM left_tmp LIMIT 1),
(SELECT lft + 2 FROM left_tmp LIMIT 1)
);
COMMIT;
Дисплей след от нижней части до вершины:
SELECT
parent.id, parent.lft
FROM
objects AS current_node
INNER JOIN
objects AS parent
ON
current_node.lft BETWEEN parent.lft AND parent.rgt
WHERE
current_node.name = 'The name of the deepest child'
ORDER BY
parent.lft;
Дисплей все дерево:
SELECT
REPEAT(' ', CAST((COUNT(parent.id) - 1) AS INT)) || '- ' || current_node.name AS indented_name
FROM
objects current_node
INNER JOIN
objects parent
ON
current_node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY
current_node.name,
current_node.lft
ORDER BY
current_node.lft;
Выбор все вниз от определенного элемента дерева:
SELECT
current_node.name AS node_name
FROM
objects current_node
INNER JOIN
objects parent
ON
current_node.lft BETWEEN parent.lft AND parent.rgt
AND
parent.name = 'child'
GROUP BY
current_node.name,
current_node.lft
ORDER BY
current_node.lft;
Если я не пропускаю что-то, рекурсия не необходима...
SELECT d.NAME FROM Customers As d
INNER JOIN Customers As p ON p.CustomerID = d.ParentID
WHERE p.Name = 'James'