Табличные параметры являются хорошим вариантом, лично я предпочитаю создавать временную таблицу в вызывающей хранимой процедуре и читать из временной таблицы в вызываемой процедуре.
Так в коде это будет:
CREATE PROC DoStuff
AS BEGIN
CREATE TABLE #tobeinserted (Data1 INT, Data2 INT...)
EXEC InsertRows
END
CREATE PROC InsertRows
AS BEGIN
INSERT INTO Table1 SELECT * FROM #tobeinserted
END
Это работает надежно, потому что временные таблицы имеют время жизни до завершения хранимой процедуры, в которой они созданы. Преимущество этого метода заключается в том, что во временных таблицах, в отличие от табличных параметров, могут быть определены (кластеризованные) индексы, поэтому поиск в этих таблицах может быть очень быстрым. Недостатком является то, что вы не можете запустить два экземпляра SP одновременно.